{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Creating a polygon from a list of points\n",
    "\n",
    "For many of those working with geo data it is a common task being asked to create a polygon from a list of points. More specific, to create a polygon that wraps around those points in a meaningful manner. So, there are several sources in the web explaining how to create the shape (see sources at end of document). This example notebook is the application of those solutions to folium maps."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Helpers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Imports\n",
    "import folium\n",
    "import random\n",
    "from scipy.spatial import ConvexHull\n",
    "\n",
    "# Function to create a list of some random points\n",
    "def randome_points(amount, LON_min, LON_max, LAT_min, LAT_max):\n",
    "\n",
    "    points = []\n",
    "    for _ in range(amount):\n",
    "        points.append((random.uniform(LON_min, LON_max),random.uniform(LAT_min, LAT_max)))\n",
    "\n",
    "    return(points)\n",
    "\n",
    "# Function to draw points in the map\n",
    "def draw_points(map_object, list_of_points, layer_name, line_color, fill_color, text):\n",
    "\n",
    "    fg = folium.FeatureGroup(name=layer_name)\n",
    "\n",
    "    for point in list_of_points:\n",
    "        fg.add_child(folium.CircleMarker(point, radius=1, color=line_color, fill_color=fill_color,\n",
    "                                         popup=(folium.Popup(text))))\n",
    "\n",
    "    map_object.add_child(fg)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Convex hull\n",
    "\n",
    "The convex hull is probably the most common approach - its goal is to create the smallest polygon that contains all points from a given list. The scipy.spatial package provides this algorithm (https://docs.scipy.org/doc/scipy-0.19.0/reference/generated/scipy.spatial.ConvexHull.html, accessed 29.12.2018)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Function that takes a map and a list of points (LON,LAT tupels) and\n",
    "# returns a map with the convex hull polygon from the points as a new layer\n",
    "\n",
    "def create_convexhull_polygon(map_object, list_of_points, layer_name, line_color, fill_color, weight, text): \n",
    "\n",
    "    # Since it is pointless to draw a convex hull polygon around less than 3 points check len of input\n",
    "    if len(list_of_points) < 3:\n",
    "        return\n",
    "\n",
    "    # Create the convex hull using scipy.spatial \n",
    "    form = [list_of_points[i] for i in ConvexHull(list_of_points).vertices]\n",
    "\n",
    "    # Create feature group, add the polygon and add the feature group to the map \n",
    "    fg = folium.FeatureGroup(name=layer_name)\n",
    "    fg.add_child(folium.vector_layers.Polygon(locations=form, color=line_color, fill_color=fill_color,\n",
    "                                              weight=weight, popup=(folium.Popup(text))))\n",
    "    map_object.add_child(fg)\n",
    "\n",
    "    return(map_object)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVM9ZmFsc2U7IExfTk9fVE9VQ0g9ZmFsc2U7IExfRElTQUJMRV8zRD1mYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4zLjQvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2FqYXguZ29vZ2xlYXBpcy5jb20vYWpheC9saWJzL2pxdWVyeS8xLjExLjEvanF1ZXJ5Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4zLjQvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdjZG4uZ2l0aGFjay5jb20vcHl0aG9uLXZpc3VhbGl6YXRpb24vZm9saXVtL21hc3Rlci9mb2xpdW0vdGVtcGxhdGVzL2xlYWZsZXQuYXdlc29tZS5yb3RhdGUuY3NzIi8+CiAgICA8c3R5bGU+aHRtbCwgYm9keSB7d2lkdGg6IDEwMCU7aGVpZ2h0OiAxMDAlO21hcmdpbjogMDtwYWRkaW5nOiAwO308L3N0eWxlPgogICAgPHN0eWxlPiNtYXAge3Bvc2l0aW9uOmFic29sdXRlO3RvcDowO2JvdHRvbTowO3JpZ2h0OjA7bGVmdDowO308L3N0eWxlPgogICAgCiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLAogICAgICAgIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEuMCwgdXNlci1zY2FsYWJsZT1ubyIgLz4KICAgIDxzdHlsZT4jbWFwX2U2OGYyMTVkMTJhYTQ0Y2JiMjZhMjI5NmJkNjBjZmU3IHsKICAgICAgICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgICAgICAgd2lkdGg6IDEwMC4wJTsKICAgICAgICBoZWlnaHQ6IDEwMC4wJTsKICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgIHRvcDogMC4wJTsKICAgICAgICB9CiAgICA8L3N0eWxlPgo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgPGRpdiBjbGFzcz0iZm9saXVtLW1hcCIgaWQ9Im1hcF9lNjhmMjE1ZDEyYWE0NGNiYjI2YTIyOTZiZDYwY2ZlNyIgPjwvZGl2Pgo8L2JvZHk+CjxzY3JpcHQ+ICAgIAogICAgCiAgICAKICAgICAgICB2YXIgYm91bmRzID0gbnVsbDsKICAgIAoKICAgIHZhciBtYXBfZTY4ZjIxNWQxMmFhNDRjYmIyNmEyMjk2YmQ2MGNmZTcgPSBMLm1hcCgKICAgICAgICAnbWFwX2U2OGYyMTVkMTJhYTQ0Y2JiMjZhMjI5NmJkNjBjZmU3JywgewogICAgICAgIGNlbnRlcjogWzQ4LjUsIDkuNV0sCiAgICAgICAgem9vbTogOCwKICAgICAgICBtYXhCb3VuZHM6IGJvdW5kcywKICAgICAgICBsYXllcnM6IFtdLAogICAgICAgIHdvcmxkQ29weUp1bXA6IGZhbHNlLAogICAgICAgIGNyczogTC5DUlMuRVBTRzM4NTcsCiAgICAgICAgem9vbUNvbnRyb2w6IHRydWUsCiAgICAgICAgfSk7CgogICAgCiAgICAKICAgIHZhciB0aWxlX2xheWVyX2U1NzExNWZhZTdkYzQ4NDliYjRiZjYwMTc1ZjY4ZDI3ID0gTC50aWxlTGF5ZXIoCiAgICAgICAgJ2h0dHBzOi8ve3N9LnRpbGUub3BlbnN0cmVldG1hcC5vcmcve3p9L3t4fS97eX0ucG5nJywKICAgICAgICB7CiAgICAgICAgImF0dHJpYnV0aW9uIjogbnVsbCwKICAgICAgICAiZGV0ZWN0UmV0aW5hIjogZmFsc2UsCiAgICAgICAgIm1heE5hdGl2ZVpvb20iOiAxOCwKICAgICAgICAibWF4Wm9vbSI6IDE4LAogICAgICAgICJtaW5ab29tIjogMCwKICAgICAgICAibm9XcmFwIjogZmFsc2UsCiAgICAgICAgIm9wYWNpdHkiOiAxLAogICAgICAgICJzdWJkb21haW5zIjogImFiYyIsCiAgICAgICAgInRtcyI6IGZhbHNlCn0pLmFkZFRvKG1hcF9lNjhmMjE1ZDEyYWE0NGNiYjI2YTIyOTZiZDYwY2ZlNyk7CiAgICAKICAgICAgICAgICAgdmFyIGZlYXR1cmVfZ3JvdXBfNWI5MDhlOTI5MGRlNGUxMmFiNDIyOTg4NTYzOWMzZDMgPSBMLmZlYXR1cmVHcm91cCgKICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2U2OGYyMTVkMTJhYTQ0Y2JiMjZhMjI5NmJkNjBjZmU3KTsKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIHBvbHlnb25fYzA2NzkwZTNlNDQzNDcxMGFiZjNjOTcyOGU3ZDVkZTMgPSBMLnBvbHlnb24oCiAgICAgICAgICAgICAgICBbWzQ4LjA3OTczNzMwNzQyMTkyLCA5LjkyMzY0MTEwMTMwOTAwMl0sIFs0OC4yNDAzNzYwNjg3NDAzNCwgOS4xNDUyMjE1NDEzMDc4NTNdLCBbNDguOTg1ODYwOTYwNDU4NzEsIDkuMzg0NDQ3NzAwMDQwMzc2XSwgWzQ4Ljg3ODUwMTk4OTE5NzY5LCA5Ljc4MDc1ODY3ODQ2NDExXSwgWzQ4LjU3NDQyODIyODQ4NDAxLCA5Ljg5MzYwMDY0MTM0NjIxM11dLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAibGlnaHRibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAibGlnaHRza3libHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjIsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJub0NsaXAiOiBmYWxzZSwKICAib3BhY2l0eSI6IDEuMCwKICAic21vb3RoRmFjdG9yIjogMS4wLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiA1Cn0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhmZWF0dXJlX2dyb3VwXzViOTA4ZTkyOTBkZTRlMTJhYjQyMjk4ODU2MzljM2QzKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzE0N2I0ZTYzZTk0NDRjMjFiNTFkNmI2NDM5MzJmZmY5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnCiAgICAgICAgICAgIAogICAgICAgICAgICB9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYjljN2Y5ZjE5ZDRiNDU5ZWE5MzdjOWUxM2Y4YTcxZGQgPSAkKGA8ZGl2IGlkPSJodG1sX2I5YzdmOWYxOWQ0YjQ1OWVhOTM3YzllMTNmOGE3MWRkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FeGFtcGxlIGNvbnZleCBodWxsPC9kaXY+YClbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8xNDdiNGU2M2U5NDQ0YzIxYjUxZDZiNjQzOTMyZmZmOS5zZXRDb250ZW50KGh0bWxfYjljN2Y5ZjE5ZDRiNDU5ZWE5MzdjOWUxM2Y4YTcxZGQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIHBvbHlnb25fYzA2NzkwZTNlNDQzNDcxMGFiZjNjOTcyOGU3ZDVkZTMuYmluZFBvcHVwKHBvcHVwXzE0N2I0ZTYzZTk0NDRjMjFiNTFkNmI2NDM5MzJmZmY5KQogICAgICAgICAgICA7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgZmVhdHVyZV9ncm91cF8wMDNlYjE2NzQ1YmU0ZmRmYjZkMDBiMmYzMmIxODdiZCA9IEwuZmVhdHVyZUdyb3VwKAogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZTY4ZjIxNWQxMmFhNDRjYmIyNmEyMjk2YmQ2MGNmZTcpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Q4NTE5OGViZGQ5NDQ5NGU5NWI5NGZkMWVlOWI0NTJhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDguOTg1ODYwOTYwNDU4NzEsIDkuMzg0NDQ3NzAwMDQwMzc2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogInJveWFsYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogInJveWFsYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC4yLAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8oZmVhdHVyZV9ncm91cF8wMDNlYjE2NzQ1YmU0ZmRmYjZkMDBiMmYzMmIxODdiZCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF84NWU4NmJiNmY3N2I0MjI3OTlhNjQ4ZTRhMTAwZWU1MyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJwogICAgICAgICAgICAKICAgICAgICAgICAgfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzIwMWZmYzRhYjE1MDRmYjFhZWMwOTgwZDVjMDVjY2VjID0gJChgPGRpdiBpZD0iaHRtbF8yMDFmZmM0YWIxNTA0ZmIxYWVjMDk4MGQ1YzA1Y2NlYyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RXhhbXBsZSBwb2ludCBmb3IgY29udmV4IGh1bGw8L2Rpdj5gKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzg1ZTg2YmI2Zjc3YjQyMjc5OWE2NDhlNGExMDBlZTUzLnNldENvbnRlbnQoaHRtbF8yMDFmZmM0YWIxNTA0ZmIxYWVjMDk4MGQ1YzA1Y2NlYyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9kODUxOThlYmRkOTQ0OTRlOTViOTRmZDFlZTliNDUyYS5iaW5kUG9wdXAocG9wdXBfODVlODZiYjZmNzdiNDIyNzk5YTY0OGU0YTEwMGVlNTMpCiAgICAgICAgICAgIDsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzQxZDFmMmFiOGJkMTRjNTBiZWQ3ZWMyNzc0YjM0OWVmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDguNjgxOTg5OTkzOTc1NiwgOS43OTk1NjE1OTk1MzMyMzRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAicm95YWxibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAicm95YWxibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjIsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhmZWF0dXJlX2dyb3VwXzAwM2ViMTY3NDViZTRmZGZiNmQwMGIyZjMyYjE4N2JkKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzRkY2MwNmUyYzA1NzQ1ZTM4ZDE1MmQ1NmUyMjZiNzhkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnCiAgICAgICAgICAgIAogICAgICAgICAgICB9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZGQ0ZGMzN2RmYjI0NGY5MzhlNzUxZmY5ZTRlZjBjMDcgPSAkKGA8ZGl2IGlkPSJodG1sX2RkNGRjMzdkZmIyNDRmOTM4ZTc1MWZmOWU0ZWYwYzA3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FeGFtcGxlIHBvaW50IGZvciBjb252ZXggaHVsbDwvZGl2PmApWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNGRjYzA2ZTJjMDU3NDVlMzhkMTUyZDU2ZTIyNmI3OGQuc2V0Q29udGVudChodG1sX2RkNGRjMzdkZmIyNDRmOTM4ZTc1MWZmOWU0ZWYwYzA3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzQxZDFmMmFiOGJkMTRjNTBiZWQ3ZWMyNzc0YjM0OWVmLmJpbmRQb3B1cChwb3B1cF80ZGNjMDZlMmMwNTc0NWUzOGQxNTJkNTZlMjI2Yjc4ZCkKICAgICAgICAgICAgOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNTljYmVmZGYwYTJlNDAzYWE3Y2YwNTc5ZDI1YThkNTEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OC4wNzk3MzczMDc0MjE5MiwgOS45MjM2NDExMDEzMDkwMDJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAicm95YWxibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAicm95YWxibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjIsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhmZWF0dXJlX2dyb3VwXzAwM2ViMTY3NDViZTRmZGZiNmQwMGIyZjMyYjE4N2JkKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzViNTNmMzY3NDMzNjQzNDc5N2ZlZTEzZjY3YWM3N2M0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnCiAgICAgICAgICAgIAogICAgICAgICAgICB9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYjIzMzAzNGY4NDZkNGZmY2I1ZmU0YjQ1YzNlYWE0OWEgPSAkKGA8ZGl2IGlkPSJodG1sX2IyMzMwMzRmODQ2ZDRmZmNiNWZlNGI0NWMzZWFhNDlhIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FeGFtcGxlIHBvaW50IGZvciBjb252ZXggaHVsbDwvZGl2PmApWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNWI1M2YzNjc0MzM2NDM0Nzk3ZmVlMTNmNjdhYzc3YzQuc2V0Q29udGVudChodG1sX2IyMzMwMzRmODQ2ZDRmZmNiNWZlNGI0NWMzZWFhNDlhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzU5Y2JlZmRmMGEyZTQwM2FhN2NmMDU3OWQyNWE4ZDUxLmJpbmRQb3B1cChwb3B1cF81YjUzZjM2NzQzMzY0MzQ3OTdmZWUxM2Y2N2FjNzdjNCkKICAgICAgICAgICAgOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNmE3OWNlM2NmODUwNGQ0MzliMGUzZWRlYTliNmYwNmMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OC4yNDAzNzYwNjg3NDAzNCwgOS4xNDUyMjE1NDEzMDc4NTNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAicm95YWxibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAicm95YWxibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjIsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhmZWF0dXJlX2dyb3VwXzAwM2ViMTY3NDViZTRmZGZiNmQwMGIyZjMyYjE4N2JkKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2U3OGIyYjI5OTE0NDRmNjJiNWIxM2I5MDQwZGM2NjZhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnCiAgICAgICAgICAgIAogICAgICAgICAgICB9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNmVjMTdkNThlZmQ2NDk2OWE2OTE2MzI0OWNlYWE4ZDcgPSAkKGA8ZGl2IGlkPSJodG1sXzZlYzE3ZDU4ZWZkNjQ5NjlhNjkxNjMyNDljZWFhOGQ3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FeGFtcGxlIHBvaW50IGZvciBjb252ZXggaHVsbDwvZGl2PmApWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZTc4YjJiMjk5MTQ0NGY2MmI1YjEzYjkwNDBkYzY2NmEuc2V0Q29udGVudChodG1sXzZlYzE3ZDU4ZWZkNjQ5NjlhNjkxNjMyNDljZWFhOGQ3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzZhNzljZTNjZjg1MDRkNDM5YjBlM2VkZWE5YjZmMDZjLmJpbmRQb3B1cChwb3B1cF9lNzhiMmIyOTkxNDQ0ZjYyYjViMTNiOTA0MGRjNjY2YSkKICAgICAgICAgICAgOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOWQzOGFmNTliMDAwNGIzMmJlOGM5M2Q0MDYxMGExNmMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OC4zMDc4NjUxNTUzMzk1MDYsIDkuODM4NDU2NTcyNzM3MzY0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogInJveWFsYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogInJveWFsYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC4yLAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8oZmVhdHVyZV9ncm91cF8wMDNlYjE2NzQ1YmU0ZmRmYjZkMDBiMmYzMmIxODdiZCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83Mzg3MDJmNjg5Y2Y0NTg1OWY0NTZlMDQzMzdmNDAyNyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJwogICAgICAgICAgICAKICAgICAgICAgICAgfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzc5ZGZmZDM3Y2U2MzQ2OTFhMTBlOWRmYjUxNTExMThlID0gJChgPGRpdiBpZD0iaHRtbF83OWRmZmQzN2NlNjM0NjkxYTEwZTlkZmI1MTUxMTE4ZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RXhhbXBsZSBwb2ludCBmb3IgY29udmV4IGh1bGw8L2Rpdj5gKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzczODcwMmY2ODljZjQ1ODU5ZjQ1NmUwNDMzN2Y0MDI3LnNldENvbnRlbnQoaHRtbF83OWRmZmQzN2NlNjM0NjkxYTEwZTlkZmI1MTUxMTE4ZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85ZDM4YWY1OWIwMDA0YjMyYmU4YzkzZDQwNjEwYTE2Yy5iaW5kUG9wdXAocG9wdXBfNzM4NzAyZjY4OWNmNDU4NTlmNDU2ZTA0MzM3ZjQwMjcpCiAgICAgICAgICAgIDsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2VhODkyNGY0ZDgzYzRhMzhiZDM1YjUwNDE5MWVhNGEzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDguODc4NTAxOTg5MTk3NjksIDkuNzgwNzU4Njc4NDY0MTFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAicm95YWxibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAicm95YWxibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjIsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhmZWF0dXJlX2dyb3VwXzAwM2ViMTY3NDViZTRmZGZiNmQwMGIyZjMyYjE4N2JkKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2RhYzJiMjIyOGM2YjQyYjZiNGY2MDc3YzVlYjY4YzFhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnCiAgICAgICAgICAgIAogICAgICAgICAgICB9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZjMyZDgxZGViNjY1NDNjOWEzZTEzNmQ5MzViMjBmMTMgPSAkKGA8ZGl2IGlkPSJodG1sX2YzMmQ4MWRlYjY2NTQzYzlhM2UxMzZkOTM1YjIwZjEzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FeGFtcGxlIHBvaW50IGZvciBjb252ZXggaHVsbDwvZGl2PmApWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZGFjMmIyMjI4YzZiNDJiNmI0ZjYwNzdjNWViNjhjMWEuc2V0Q29udGVudChodG1sX2YzMmQ4MWRlYjY2NTQzYzlhM2UxMzZkOTM1YjIwZjEzKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2VhODkyNGY0ZDgzYzRhMzhiZDM1YjUwNDE5MWVhNGEzLmJpbmRQb3B1cChwb3B1cF9kYWMyYjIyMjhjNmI0MmI2YjRmNjA3N2M1ZWI2OGMxYSkKICAgICAgICAgICAgOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYjg3MTY3MDllY2FhNDJiYjhkMDFjZjg4NTQzYjYzYWEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OC41NzQ0MjgyMjg0ODQwMSwgOS44OTM2MDA2NDEzNDYyMTNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAicm95YWxibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAicm95YWxibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjIsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhmZWF0dXJlX2dyb3VwXzAwM2ViMTY3NDViZTRmZGZiNmQwMGIyZjMyYjE4N2JkKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzBkOWVkM2I0OTJiZDQxMTFhZjgzYTMxYzk4ZDI2MjU4ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnCiAgICAgICAgICAgIAogICAgICAgICAgICB9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNDk4ZjRjZTEwMmU5NDBjODljMGIxM2NiNzQ3MmM2ODAgPSAkKGA8ZGl2IGlkPSJodG1sXzQ5OGY0Y2UxMDJlOTQwYzg5YzBiMTNjYjc0NzJjNjgwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FeGFtcGxlIHBvaW50IGZvciBjb252ZXggaHVsbDwvZGl2PmApWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMGQ5ZWQzYjQ5MmJkNDExMWFmODNhMzFjOThkMjYyNTguc2V0Q29udGVudChodG1sXzQ5OGY0Y2UxMDJlOTQwYzg5YzBiMTNjYjc0NzJjNjgwKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2I4NzE2NzA5ZWNhYTQyYmI4ZDAxY2Y4ODU0M2I2M2FhLmJpbmRQb3B1cChwb3B1cF8wZDllZDNiNDkyYmQ0MTExYWY4M2EzMWM5OGQyNjI1OCkKICAgICAgICAgICAgOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMjNmZDdkZmE5MDIxNDFjZmFlZjUxNDkxNjNmOWYxMTggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OC4zMDI1OTU0MTMwNzQ4OSwgOS43NTIwMDA4MTM0NzI0NjJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAicm95YWxibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAicm95YWxibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjIsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhmZWF0dXJlX2dyb3VwXzAwM2ViMTY3NDViZTRmZGZiNmQwMGIyZjMyYjE4N2JkKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzIxMGM4OWIxNWYwODQ4YmU4YTUzYzFmMjdiNWM5MDY0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnCiAgICAgICAgICAgIAogICAgICAgICAgICB9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNDUyYjg5OTgwMWRlNDY2YWJmOTQyODYxM2MyZGI3MzAgPSAkKGA8ZGl2IGlkPSJodG1sXzQ1MmI4OTk4MDFkZTQ2NmFiZjk0Mjg2MTNjMmRiNzMwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FeGFtcGxlIHBvaW50IGZvciBjb252ZXggaHVsbDwvZGl2PmApWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjEwYzg5YjE1ZjA4NDhiZThhNTNjMWYyN2I1YzkwNjQuc2V0Q29udGVudChodG1sXzQ1MmI4OTk4MDFkZTQ2NmFiZjk0Mjg2MTNjMmRiNzMwKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzIzZmQ3ZGZhOTAyMTQxY2ZhZWY1MTQ5MTYzZjlmMTE4LmJpbmRQb3B1cChwb3B1cF8yMTBjODliMTVmMDg0OGJlOGE1M2MxZjI3YjVjOTA2NCkKICAgICAgICAgICAgOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZGVhMmVmN2RmNjAzNDJmN2I0YzA4NjRiYTk0MTlhNWEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OC4yODcwODg2MzcyNjk4NTQsIDkuMjg3ODEzNjU1MTYyNjEyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogInJveWFsYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogInJveWFsYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC4yLAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8oZmVhdHVyZV9ncm91cF8wMDNlYjE2NzQ1YmU0ZmRmYjZkMDBiMmYzMmIxODdiZCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xYWJiNmE3NjNmYjU0MGVlYTEzNmU0ZjliN2I0Yzc3NyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJwogICAgICAgICAgICAKICAgICAgICAgICAgfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2Y1ZmMxNjFkN2I5OTQ0M2I4OTZhMmI2YWViYTU0OTVkID0gJChgPGRpdiBpZD0iaHRtbF9mNWZjMTYxZDdiOTk0NDNiODk2YTJiNmFlYmE1NDk1ZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RXhhbXBsZSBwb2ludCBmb3IgY29udmV4IGh1bGw8L2Rpdj5gKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzFhYmI2YTc2M2ZiNTQwZWVhMTM2ZTRmOWI3YjRjNzc3LnNldENvbnRlbnQoaHRtbF9mNWZjMTYxZDdiOTk0NDNiODk2YTJiNmFlYmE1NDk1ZCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9kZWEyZWY3ZGY2MDM0MmY3YjRjMDg2NGJhOTQxOWE1YS5iaW5kUG9wdXAocG9wdXBfMWFiYjZhNzYzZmI1NDBlZWExMzZlNGY5YjdiNGM3NzcpCiAgICAgICAgICAgIDsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2I3N2FiNTM2ZDUzODRjMDBhNzExZjkzOGEyN2IwMTdhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDguMjM5NTE4ODgxMzczMzg1LCA5LjI3MTE0MzUxNTYwNDczNl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJyb3lhbGJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJyb3lhbGJsdWUiLAogICJmaWxsT3BhY2l0eSI6IDAuMiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDEsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKGZlYXR1cmVfZ3JvdXBfMDAzZWIxNjc0NWJlNGZkZmI2ZDAwYjJmMzJiMTg3YmQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNzdjM2MyZTc5MTkyNGYzYmFjODNmOGI3NzgzZjRlYjYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCcKICAgICAgICAgICAgCiAgICAgICAgICAgIH0pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mYWRjODExODA5NzE0NThkOGJjMzIzMjZlZGExYzZiZiA9ICQoYDxkaXYgaWQ9Imh0bWxfZmFkYzgxMTgwOTcxNDU4ZDhiYzMyMzI2ZWRhMWM2YmYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkV4YW1wbGUgcG9pbnQgZm9yIGNvbnZleCBodWxsPC9kaXY+YClbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83N2MzYzJlNzkxOTI0ZjNiYWM4M2Y4Yjc3ODNmNGViNi5zZXRDb250ZW50KGh0bWxfZmFkYzgxMTgwOTcxNDU4ZDhiYzMyMzI2ZWRhMWM2YmYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYjc3YWI1MzZkNTM4NGMwMGE3MTFmOTM4YTI3YjAxN2EuYmluZFBvcHVwKHBvcHVwXzc3YzNjMmU3OTE5MjRmM2JhYzgzZjhiNzc4M2Y0ZWI2KQogICAgICAgICAgICA7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgbGF5ZXJfY29udHJvbF82OTM4ZjkzMjY4Y2I0ZGEwOGViZmJhZmIzYmEzN2NiOSA9IHsKICAgICAgICAgICAgICAgIGJhc2VfbGF5ZXJzIDogeyAib3BlbnN0cmVldG1hcCIgOiB0aWxlX2xheWVyX2U1NzExNWZhZTdkYzQ4NDliYjRiZjYwMTc1ZjY4ZDI3LCB9LAogICAgICAgICAgICAgICAgb3ZlcmxheXMgOiB7ICJFeGFtcGxlIGNvbnZleCBodWxsIiA6IGZlYXR1cmVfZ3JvdXBfNWI5MDhlOTI5MGRlNGUxMmFiNDIyOTg4NTYzOWMzZDMsIkV4YW1wbGUgcG9pbnRzIGZvciBjb252ZXggaHVsbCIgOiBmZWF0dXJlX2dyb3VwXzAwM2ViMTY3NDViZTRmZGZiNmQwMGIyZjMyYjE4N2JkLCB9CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICBMLmNvbnRyb2wubGF5ZXJzKAogICAgICAgICAgICAgICAgbGF5ZXJfY29udHJvbF82OTM4ZjkzMjY4Y2I0ZGEwOGViZmJhZmIzYmEzN2NiOS5iYXNlX2xheWVycywKICAgICAgICAgICAgICAgIGxheWVyX2NvbnRyb2xfNjkzOGY5MzI2OGNiNGRhMDhlYmZiYWZiM2JhMzdjYjkub3ZlcmxheXMsCiAgICAgICAgICAgICAgICB7cG9zaXRpb246ICd0b3ByaWdodCcsCiAgICAgICAgICAgICAgICAgY29sbGFwc2VkOiBmYWxzZSwKICAgICAgICAgICAgICAgICBhdXRvWkluZGV4OiB0cnVlCiAgICAgICAgICAgICAgICB9KS5hZGRUbyhtYXBfZTY4ZjIxNWQxMmFhNDRjYmIyNmEyMjk2YmQ2MGNmZTcpOwogICAgICAgICAgICAKICAgICAgICAKPC9zY3JpcHQ+\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
      ],
      "text/plain": [
       "<folium.folium.Map at 0x933cc18>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Initialize map\n",
    "my_convexhull_map = folium.Map(location=[48.5, 9.5], zoom_start=8)\n",
    "\n",
    "# Create a convex hull polygon that contains some points\n",
    "list_of_points = randome_points(amount=10, LON_min=48, LON_max=49, LAT_min=9, LAT_max=10)\n",
    "\n",
    "create_convexhull_polygon(my_convexhull_map, list_of_points, layer_name='Example convex hull',\n",
    "                        line_color='lightblue', fill_color='lightskyblue', weight=5, text='Example convex hull') \n",
    "\n",
    "draw_points(my_convexhull_map, list_of_points, layer_name='Example points for convex hull',\n",
    "           line_color='royalblue', fill_color='royalblue', text='Example point for convex hull')\n",
    "\n",
    "# Add layer control and show map\n",
    "folium.LayerControl(collapsed=False).add_to(my_convexhull_map)\n",
    "my_convexhull_map"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Envelope\n",
    "\n",
    "The envelope is another interesting approach - its goal is to create a box that contains all points from a given list."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def create_envelope_polygon(map_object, list_of_points, layer_name, line_color, fill_color, weight, text):\n",
    "\n",
    "    # Since it is pointless to draw a box around less than 2 points check len of input\n",
    "    if len(list_of_points) < 2:\n",
    "        return\n",
    "\n",
    "    # Find the edges of box\n",
    "    from operator import itemgetter\n",
    "    list_of_points = sorted(list_of_points,key=itemgetter(0))\n",
    "    x_min = list_of_points[0]\n",
    "    x_max = list_of_points[len(list_of_points)-1]\n",
    "\n",
    "    list_of_points = sorted(list_of_points,key=itemgetter(1))\n",
    "    y_min = list_of_points[0]\n",
    "    y_max = list_of_points[len(list_of_points)-1]\n",
    "\n",
    "    upper_left = (x_min[0], y_max[1])\n",
    "    upper_right = (x_max[0], y_max[1])\n",
    "    lower_right = (x_max[0], y_min[1])\n",
    "    lower_left = (x_min[0], y_min[1])\n",
    "\n",
    "    edges = [upper_left, upper_right, lower_right, lower_left]\n",
    "\n",
    "    # Create feature group, add the polygon and add the feature group to the map \n",
    "    fg = folium.FeatureGroup(name=layer_name)\n",
    "    fg.add_child(folium.vector_layers.Polygon(locations=edges, color=line_color, fill_color=fill_color,\n",
    "                                              weight=weight, popup=(folium.Popup(text))))\n",
    "    map_object.add_child(fg)\n",
    "\n",
    "    return(map_object)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVM9ZmFsc2U7IExfTk9fVE9VQ0g9ZmFsc2U7IExfRElTQUJMRV8zRD1mYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4zLjQvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2FqYXguZ29vZ2xlYXBpcy5jb20vYWpheC9saWJzL2pxdWVyeS8xLjExLjEvanF1ZXJ5Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4zLjQvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdjZG4uZ2l0aGFjay5jb20vcHl0aG9uLXZpc3VhbGl6YXRpb24vZm9saXVtL21hc3Rlci9mb2xpdW0vdGVtcGxhdGVzL2xlYWZsZXQuYXdlc29tZS5yb3RhdGUuY3NzIi8+CiAgICA8c3R5bGU+aHRtbCwgYm9keSB7d2lkdGg6IDEwMCU7aGVpZ2h0OiAxMDAlO21hcmdpbjogMDtwYWRkaW5nOiAwO308L3N0eWxlPgogICAgPHN0eWxlPiNtYXAge3Bvc2l0aW9uOmFic29sdXRlO3RvcDowO2JvdHRvbTowO3JpZ2h0OjA7bGVmdDowO308L3N0eWxlPgogICAgCiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLAogICAgICAgIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEuMCwgdXNlci1zY2FsYWJsZT1ubyIgLz4KICAgIDxzdHlsZT4jbWFwX2VkYWNiMTc2ZmUwNzQ1NDBhMGIwMjQxMmE5NGZhYjQyIHsKICAgICAgICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgICAgICAgd2lkdGg6IDEwMC4wJTsKICAgICAgICBoZWlnaHQ6IDEwMC4wJTsKICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgIHRvcDogMC4wJTsKICAgICAgICB9CiAgICA8L3N0eWxlPgo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgPGRpdiBjbGFzcz0iZm9saXVtLW1hcCIgaWQ9Im1hcF9lZGFjYjE3NmZlMDc0NTQwYTBiMDI0MTJhOTRmYWI0MiIgPjwvZGl2Pgo8L2JvZHk+CjxzY3JpcHQ+ICAgIAogICAgCiAgICAKICAgICAgICB2YXIgYm91bmRzID0gbnVsbDsKICAgIAoKICAgIHZhciBtYXBfZWRhY2IxNzZmZTA3NDU0MGEwYjAyNDEyYTk0ZmFiNDIgPSBMLm1hcCgKICAgICAgICAnbWFwX2VkYWNiMTc2ZmUwNzQ1NDBhMGIwMjQxMmE5NGZhYjQyJywgewogICAgICAgIGNlbnRlcjogWzQ5LjUsIDguNV0sCiAgICAgICAgem9vbTogOCwKICAgICAgICBtYXhCb3VuZHM6IGJvdW5kcywKICAgICAgICBsYXllcnM6IFtdLAogICAgICAgIHdvcmxkQ29weUp1bXA6IGZhbHNlLAogICAgICAgIGNyczogTC5DUlMuRVBTRzM4NTcsCiAgICAgICAgem9vbUNvbnRyb2w6IHRydWUsCiAgICAgICAgfSk7CgogICAgCiAgICAKICAgIHZhciB0aWxlX2xheWVyXzBkZjI3NzdmMWY4NTRmNzViZmI2MGQ4MDk0NmY2MDQ1ID0gTC50aWxlTGF5ZXIoCiAgICAgICAgJ2h0dHBzOi8ve3N9LnRpbGUub3BlbnN0cmVldG1hcC5vcmcve3p9L3t4fS97eX0ucG5nJywKICAgICAgICB7CiAgICAgICAgImF0dHJpYnV0aW9uIjogbnVsbCwKICAgICAgICAiZGV0ZWN0UmV0aW5hIjogZmFsc2UsCiAgICAgICAgIm1heE5hdGl2ZVpvb20iOiAxOCwKICAgICAgICAibWF4Wm9vbSI6IDE4LAogICAgICAgICJtaW5ab29tIjogMCwKICAgICAgICAibm9XcmFwIjogZmFsc2UsCiAgICAgICAgIm9wYWNpdHkiOiAxLAogICAgICAgICJzdWJkb21haW5zIjogImFiYyIsCiAgICAgICAgInRtcyI6IGZhbHNlCn0pLmFkZFRvKG1hcF9lZGFjYjE3NmZlMDc0NTQwYTBiMDI0MTJhOTRmYWI0Mik7CiAgICAKICAgICAgICAgICAgdmFyIGZlYXR1cmVfZ3JvdXBfNjkxNmQwYzI0NzFjNDYyYjg0Y2E5ZThlYTdjZjhiZGUgPSBMLmZlYXR1cmVHcm91cCgKICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VkYWNiMTc2ZmUwNzQ1NDBhMGIwMjQxMmE5NGZhYjQyKTsKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIHBvbHlnb25fZDFlOTk0Y2E4MWY2NDEzMmFhNmZmMTc4ZDMwZDM1NmMgPSBMLnBvbHlnb24oCiAgICAgICAgICAgICAgICBbWzQ5LjEzNjA5NDgwNzg5NDE0LCA4Ljk4NzY1MjAwNzE5OTIzMl0sIFs0OS45OTk5OTc0MDc5NDc3MiwgOC45ODc2NTIwMDcxOTkyMzJdLCBbNDkuOTk5OTk3NDA3OTQ3NzIsIDguMTA4OTY0NzE3OTUwMzI5XSwgWzQ5LjEzNjA5NDgwNzg5NDE0LCA4LjEwODk2NDcxNzk1MDMyOV1dLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiaW5kaWFucmVkIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAicmVkIiwKICAiZmlsbE9wYWNpdHkiOiAwLjIsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJub0NsaXAiOiBmYWxzZSwKICAib3BhY2l0eSI6IDEuMCwKICAic21vb3RoRmFjdG9yIjogMS4wLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiA1Cn0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhmZWF0dXJlX2dyb3VwXzY5MTZkMGMyNDcxYzQ2MmI4NGNhOWU4ZWE3Y2Y4YmRlKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzI0MTdiZTVhYzVhYzQ1ZGZhNzRhZWYwOTZkYjRmMzk0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnCiAgICAgICAgICAgIAogICAgICAgICAgICB9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfM2RlMGJlMmY4ZGNjNGM2MmE2Y2VmZDZkMjNiYzdjZDkgPSAkKGA8ZGl2IGlkPSJodG1sXzNkZTBiZTJmOGRjYzRjNjJhNmNlZmQ2ZDIzYmM3Y2Q5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FeGFtcGxlIGVudmVsb3BlPC9kaXY+YClbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yNDE3YmU1YWM1YWM0NWRmYTc0YWVmMDk2ZGI0ZjM5NC5zZXRDb250ZW50KGh0bWxfM2RlMGJlMmY4ZGNjNGM2MmE2Y2VmZDZkMjNiYzdjZDkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIHBvbHlnb25fZDFlOTk0Y2E4MWY2NDEzMmFhNmZmMTc4ZDMwZDM1NmMuYmluZFBvcHVwKHBvcHVwXzI0MTdiZTVhYzVhYzQ1ZGZhNzRhZWYwOTZkYjRmMzk0KQogICAgICAgICAgICA7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgZmVhdHVyZV9ncm91cF8yMTBhOWIwYTIyZTc0ZTVjOTRlMjEyN2MzNTE0MWFjNSA9IEwuZmVhdHVyZUdyb3VwKAogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWRhY2IxNzZmZTA3NDU0MGEwYjAyNDEyYTk0ZmFiNDIpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzRkNTUzYzk3YTdjNjRiODU4ZTVkYzQ0MDk0NmRhNDEzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDkuNDg5NDExODE4NTg0OTM0LCA4LjEwODk2NDcxNzk1MDMyOV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJkYXJrcmVkIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiZGFya3JlZCIsCiAgImZpbGxPcGFjaXR5IjogMC4yLAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8oZmVhdHVyZV9ncm91cF8yMTBhOWIwYTIyZTc0ZTVjOTRlMjEyN2MzNTE0MWFjNSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80Yzg5YTQwY2MxMTI0YjU0YjQzM2Y2NzQxYjZmOTI0NCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJwogICAgICAgICAgICAKICAgICAgICAgICAgfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2ViYjJlYzRiMmY2MjRhMzdiZDdmOTFlMzMwMTk1ZDA1ID0gJChgPGRpdiBpZD0iaHRtbF9lYmIyZWM0YjJmNjI0YTM3YmQ3ZjkxZTMzMDE5NWQwNSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RXhhbXBsZSBwb2ludCBmb3IgZW52ZWxvcGU8L2Rpdj5gKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzRjODlhNDBjYzExMjRiNTRiNDMzZjY3NDFiNmY5MjQ0LnNldENvbnRlbnQoaHRtbF9lYmIyZWM0YjJmNjI0YTM3YmQ3ZjkxZTMzMDE5NWQwNSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl80ZDU1M2M5N2E3YzY0Yjg1OGU1ZGM0NDA5NDZkYTQxMy5iaW5kUG9wdXAocG9wdXBfNGM4OWE0MGNjMTEyNGI1NGI0MzNmNjc0MWI2ZjkyNDQpCiAgICAgICAgICAgIDsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzJmYmUxMTQ4ZTk2ZDQ1ZTg5NTE4MzdiYmJjMjIwOGQ2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDkuOTk5OTk3NDA3OTQ3NzIsIDguNjgzMjUzNjE5NTUxNDM4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImRhcmtyZWQiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJkYXJrcmVkIiwKICAiZmlsbE9wYWNpdHkiOiAwLjIsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhmZWF0dXJlX2dyb3VwXzIxMGE5YjBhMjJlNzRlNWM5NGUyMTI3YzM1MTQxYWM1KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzdmY2I0MjgzNjNhMzQ4ODk5OGYyY2U0ZjRmMzIxMjYxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnCiAgICAgICAgICAgIAogICAgICAgICAgICB9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMWU0MjM3YTQzOTMwNGZhOGFlODgyMmNhNGM0MTYzNzUgPSAkKGA8ZGl2IGlkPSJodG1sXzFlNDIzN2E0MzkzMDRmYThhZTg4MjJjYTRjNDE2Mzc1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FeGFtcGxlIHBvaW50IGZvciBlbnZlbG9wZTwvZGl2PmApWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfN2ZjYjQyODM2M2EzNDg4OTk4ZjJjZTRmNGYzMjEyNjEuc2V0Q29udGVudChodG1sXzFlNDIzN2E0MzkzMDRmYThhZTg4MjJjYTRjNDE2Mzc1KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzJmYmUxMTQ4ZTk2ZDQ1ZTg5NTE4MzdiYmJjMjIwOGQ2LmJpbmRQb3B1cChwb3B1cF83ZmNiNDI4MzYzYTM0ODg5OThmMmNlNGY0ZjMyMTI2MSkKICAgICAgICAgICAgOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYjI2NjNhMTEwMjI0NGZiYTg4ZjViOWNmM2NjOGU2YTggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OS44OTAyNTgzMjQ4MzA4MjUsIDguNDg3MjU4NjI3ODk1OTMxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImRhcmtyZWQiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJkYXJrcmVkIiwKICAiZmlsbE9wYWNpdHkiOiAwLjIsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhmZWF0dXJlX2dyb3VwXzIxMGE5YjBhMjJlNzRlNWM5NGUyMTI3YzM1MTQxYWM1KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2VlYjg4ZDBiYzhjYTRmNDI5ZGY4NTBjNTE1MGU5ZWIzID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnCiAgICAgICAgICAgIAogICAgICAgICAgICB9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYTJmOTI3OWI4MzM0NDA4ZGIwOWY3MTI2YTFjOGY4MjQgPSAkKGA8ZGl2IGlkPSJodG1sX2EyZjkyNzliODMzNDQwOGRiMDlmNzEyNmExYzhmODI0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FeGFtcGxlIHBvaW50IGZvciBlbnZlbG9wZTwvZGl2PmApWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZWViODhkMGJjOGNhNGY0MjlkZjg1MGM1MTUwZTllYjMuc2V0Q29udGVudChodG1sX2EyZjkyNzliODMzNDQwOGRiMDlmNzEyNmExYzhmODI0KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2IyNjYzYTExMDIyNDRmYmE4OGY1YjljZjNjYzhlNmE4LmJpbmRQb3B1cChwb3B1cF9lZWI4OGQwYmM4Y2E0ZjQyOWRmODUwYzUxNTBlOWViMykKICAgICAgICAgICAgOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNDEyMjhkZmJhYjJlNDVlZDllYjM1NzI2ZDE2OGMxNjggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OS40NDY2NzE4MzA4MzYwOCwgOC43MDY3Njk5MTcwOTIyOTFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiZGFya3JlZCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImRhcmtyZWQiLAogICJmaWxsT3BhY2l0eSI6IDAuMiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDEsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKGZlYXR1cmVfZ3JvdXBfMjEwYTliMGEyMmU3NGU1Yzk0ZTIxMjdjMzUxNDFhYzUpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMTY5YWY0ZjRkMTFkNDI5MmIzMmE3ZjNiOTExNDYyNzEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCcKICAgICAgICAgICAgCiAgICAgICAgICAgIH0pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80OGNlNjk4Y2ZlM2M0ZDNhYWNlYWZmZTJkZTExY2UxZSA9ICQoYDxkaXYgaWQ9Imh0bWxfNDhjZTY5OGNmZTNjNGQzYWFjZWFmZmUyZGUxMWNlMWUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkV4YW1wbGUgcG9pbnQgZm9yIGVudmVsb3BlPC9kaXY+YClbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8xNjlhZjRmNGQxMWQ0MjkyYjMyYTdmM2I5MTE0NjI3MS5zZXRDb250ZW50KGh0bWxfNDhjZTY5OGNmZTNjNGQzYWFjZWFmZmUyZGUxMWNlMWUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNDEyMjhkZmJhYjJlNDVlZDllYjM1NzI2ZDE2OGMxNjguYmluZFBvcHVwKHBvcHVwXzE2OWFmNGY0ZDExZDQyOTJiMzJhN2YzYjkxMTQ2MjcxKQogICAgICAgICAgICA7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jZTZjMzNjZGQzNjA0OWNmYmM3ZWM4YWMwZjVlNjRjMSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ5Ljk1OTkwNTg5MTQxODIyLCA4Ljk2NjI2MjgzMzI4ODE5M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJkYXJrcmVkIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiZGFya3JlZCIsCiAgImZpbGxPcGFjaXR5IjogMC4yLAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8oZmVhdHVyZV9ncm91cF8yMTBhOWIwYTIyZTc0ZTVjOTRlMjEyN2MzNTE0MWFjNSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xM2EzODI3NTkxYTY0NmJjOTVjNmMxMjk0NTliMDRkMCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJwogICAgICAgICAgICAKICAgICAgICAgICAgfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzk1NDA1MTRlOTE3NjRlMWFhYTc1M2Q2OGM5ZTk0Njc3ID0gJChgPGRpdiBpZD0iaHRtbF85NTQwNTE0ZTkxNzY0ZTFhYWE3NTNkNjhjOWU5NDY3NyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RXhhbXBsZSBwb2ludCBmb3IgZW52ZWxvcGU8L2Rpdj5gKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzEzYTM4Mjc1OTFhNjQ2YmM5NWM2YzEyOTQ1OWIwNGQwLnNldENvbnRlbnQoaHRtbF85NTQwNTE0ZTkxNzY0ZTFhYWE3NTNkNjhjOWU5NDY3Nyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jZTZjMzNjZGQzNjA0OWNmYmM3ZWM4YWMwZjVlNjRjMS5iaW5kUG9wdXAocG9wdXBfMTNhMzgyNzU5MWE2NDZiYzk1YzZjMTI5NDU5YjA0ZDApCiAgICAgICAgICAgIDsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzY1OWE4MDEyOWMzMjQ5MzNiNTIzYzA1NDk0YWQyMmI3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDkuNTA0MjAwODYxNTczMjgsIDguOTQ5MDIwOTk2MjI4MjU2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImRhcmtyZWQiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJkYXJrcmVkIiwKICAiZmlsbE9wYWNpdHkiOiAwLjIsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhmZWF0dXJlX2dyb3VwXzIxMGE5YjBhMjJlNzRlNWM5NGUyMTI3YzM1MTQxYWM1KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2M3YjdkM2Q4NWFmNjRhOGU5ZmY2ZjA1NTlkZmU0ZjllID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnCiAgICAgICAgICAgIAogICAgICAgICAgICB9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMzkyMDMzZjU1NjRkNGMxYmEyY2Q3MzQ2MWViNGE0YzQgPSAkKGA8ZGl2IGlkPSJodG1sXzM5MjAzM2Y1NTY0ZDRjMWJhMmNkNzM0NjFlYjRhNGM0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FeGFtcGxlIHBvaW50IGZvciBlbnZlbG9wZTwvZGl2PmApWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYzdiN2QzZDg1YWY2NGE4ZTlmZjZmMDU1OWRmZTRmOWUuc2V0Q29udGVudChodG1sXzM5MjAzM2Y1NTY0ZDRjMWJhMmNkNzM0NjFlYjRhNGM0KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzY1OWE4MDEyOWMzMjQ5MzNiNTIzYzA1NDk0YWQyMmI3LmJpbmRQb3B1cChwb3B1cF9jN2I3ZDNkODVhZjY0YThlOWZmNmYwNTU5ZGZlNGY5ZSkKICAgICAgICAgICAgOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNzE4YTc4NGY2ZTUwNGVjYjliZTcxNmFjZTIzNjdkNDggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OS4xMzYwOTQ4MDc4OTQxNCwgOC42MDc2NDMyNDc2NTAyMjVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiZGFya3JlZCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImRhcmtyZWQiLAogICJmaWxsT3BhY2l0eSI6IDAuMiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDEsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKGZlYXR1cmVfZ3JvdXBfMjEwYTliMGEyMmU3NGU1Yzk0ZTIxMjdjMzUxNDFhYzUpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjM1YjFiN2JhZmY1NDY1Y2IwNjFiZjAzODM5M2NlMzkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCcKICAgICAgICAgICAgCiAgICAgICAgICAgIH0pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81YmYyZWMxNDY1NTc0MzkxYWYyZjIyNTcyYmUyMWMyMyA9ICQoYDxkaXYgaWQ9Imh0bWxfNWJmMmVjMTQ2NTU3NDM5MWFmMmYyMjU3MmJlMjFjMjMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkV4YW1wbGUgcG9pbnQgZm9yIGVudmVsb3BlPC9kaXY+YClbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82MzViMWI3YmFmZjU0NjVjYjA2MWJmMDM4MzkzY2UzOS5zZXRDb250ZW50KGh0bWxfNWJmMmVjMTQ2NTU3NDM5MWFmMmYyMjU3MmJlMjFjMjMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNzE4YTc4NGY2ZTUwNGVjYjliZTcxNmFjZTIzNjdkNDguYmluZFBvcHVwKHBvcHVwXzYzNWIxYjdiYWZmNTQ2NWNiMDYxYmYwMzgzOTNjZTM5KQogICAgICAgICAgICA7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9lNjQ3ZWRjNjA4OTI0MDU3YmYxMTlhYjk3NjQ3Yjg1MCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ5LjgwMzkyNzA0NzQ3NzkzNCwgOC44NDMxNDEzMTEwNjc4NTddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiZGFya3JlZCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImRhcmtyZWQiLAogICJmaWxsT3BhY2l0eSI6IDAuMiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDEsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKGZlYXR1cmVfZ3JvdXBfMjEwYTliMGEyMmU3NGU1Yzk0ZTIxMjdjMzUxNDFhYzUpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNzE3YjliODQwZWQzNGM3NTgyNTUyZjc0Nzk0NzQyYzggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCcKICAgICAgICAgICAgCiAgICAgICAgICAgIH0pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lYTM4NTlkMzZlMWE0NDg1YjcwZWMwZGRiODJkNTY4OCA9ICQoYDxkaXYgaWQ9Imh0bWxfZWEzODU5ZDM2ZTFhNDQ4NWI3MGVjMGRkYjgyZDU2ODgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkV4YW1wbGUgcG9pbnQgZm9yIGVudmVsb3BlPC9kaXY+YClbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83MTdiOWI4NDBlZDM0Yzc1ODI1NTJmNzQ3OTQ3NDJjOC5zZXRDb250ZW50KGh0bWxfZWEzODU5ZDM2ZTFhNDQ4NWI3MGVjMGRkYjgyZDU2ODgpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZTY0N2VkYzYwODkyNDA1N2JmMTE5YWI5NzY0N2I4NTAuYmluZFBvcHVwKHBvcHVwXzcxN2I5Yjg0MGVkMzRjNzU4MjU1MmY3NDc5NDc0MmM4KQogICAgICAgICAgICA7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mZjU2ODBhNDMzNDk0NWQxYTQ1OGFlN2RiMzU4YWYwNSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ5LjcwMDU4MDA2MTQ1NzgzNSwgOC45ODc2NTIwMDcxOTkyMzJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiZGFya3JlZCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImRhcmtyZWQiLAogICJmaWxsT3BhY2l0eSI6IDAuMiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDEsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKGZlYXR1cmVfZ3JvdXBfMjEwYTliMGEyMmU3NGU1Yzk0ZTIxMjdjMzUxNDFhYzUpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOTcxYzcwOWNhMGQ3NGM2MThhY2Q2ZjUxZjA0YzI5YzAgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCcKICAgICAgICAgICAgCiAgICAgICAgICAgIH0pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81NWEwNzIyNDAwZjk0YmQ2OWNiNDNiYzdjZWNlZDcxMyA9ICQoYDxkaXYgaWQ9Imh0bWxfNTVhMDcyMjQwMGY5NGJkNjljYjQzYmM3Y2VjZWQ3MTMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkV4YW1wbGUgcG9pbnQgZm9yIGVudmVsb3BlPC9kaXY+YClbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85NzFjNzA5Y2EwZDc0YzYxOGFjZDZmNTFmMDRjMjljMC5zZXRDb250ZW50KGh0bWxfNTVhMDcyMjQwMGY5NGJkNjljYjQzYmM3Y2VjZWQ3MTMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZmY1NjgwYTQzMzQ5NDVkMWE0NThhZTdkYjM1OGFmMDUuYmluZFBvcHVwKHBvcHVwXzk3MWM3MDljYTBkNzRjNjE4YWNkNmY1MWYwNGMyOWMwKQogICAgICAgICAgICA7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xNmYxYjZkMWRmYzg0YTM1OTQ5MTlmYWYxZmU3NWE4OCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ5LjE4MTQzMzUzMDQ2MDYxNiwgOC42MDMzNTUwNTUzNjE4MTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiZGFya3JlZCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImRhcmtyZWQiLAogICJmaWxsT3BhY2l0eSI6IDAuMiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDEsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKGZlYXR1cmVfZ3JvdXBfMjEwYTliMGEyMmU3NGU1Yzk0ZTIxMjdjMzUxNDFhYzUpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMjUxNmNmZGUzNTZlNGQyY2FmNjk5ZjRlZTllYTc0NmYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCcKICAgICAgICAgICAgCiAgICAgICAgICAgIH0pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lOTBhNWRkYTczNTc0ZTdmOWYyOTUzNDBiN2M2MmE1MCA9ICQoYDxkaXYgaWQ9Imh0bWxfZTkwYTVkZGE3MzU3NGU3ZjlmMjk1MzQwYjdjNjJhNTAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkV4YW1wbGUgcG9pbnQgZm9yIGVudmVsb3BlPC9kaXY+YClbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yNTE2Y2ZkZTM1NmU0ZDJjYWY2OTlmNGVlOWVhNzQ2Zi5zZXRDb250ZW50KGh0bWxfZTkwYTVkZGE3MzU3NGU3ZjlmMjk1MzQwYjdjNjJhNTApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMTZmMWI2ZDFkZmM4NGEzNTk0OTE5ZmFmMWZlNzVhODguYmluZFBvcHVwKHBvcHVwXzI1MTZjZmRlMzU2ZTRkMmNhZjY5OWY0ZWU5ZWE3NDZmKQogICAgICAgICAgICA7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgbGF5ZXJfY29udHJvbF8wOThlOWI3YjJhMzU0ZGRiODAyOWVkMDUxOTMyYzIzYiA9IHsKICAgICAgICAgICAgICAgIGJhc2VfbGF5ZXJzIDogeyAib3BlbnN0cmVldG1hcCIgOiB0aWxlX2xheWVyXzBkZjI3NzdmMWY4NTRmNzViZmI2MGQ4MDk0NmY2MDQ1LCB9LAogICAgICAgICAgICAgICAgb3ZlcmxheXMgOiB7ICJFeGFtcGxlIGVudmVsb3BlIiA6IGZlYXR1cmVfZ3JvdXBfNjkxNmQwYzI0NzFjNDYyYjg0Y2E5ZThlYTdjZjhiZGUsIkV4YW1wbGUgcG9pbnRzIGZvciBlbnZlbG9wZSIgOiBmZWF0dXJlX2dyb3VwXzIxMGE5YjBhMjJlNzRlNWM5NGUyMTI3YzM1MTQxYWM1LCB9CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICBMLmNvbnRyb2wubGF5ZXJzKAogICAgICAgICAgICAgICAgbGF5ZXJfY29udHJvbF8wOThlOWI3YjJhMzU0ZGRiODAyOWVkMDUxOTMyYzIzYi5iYXNlX2xheWVycywKICAgICAgICAgICAgICAgIGxheWVyX2NvbnRyb2xfMDk4ZTliN2IyYTM1NGRkYjgwMjllZDA1MTkzMmMyM2Iub3ZlcmxheXMsCiAgICAgICAgICAgICAgICB7cG9zaXRpb246ICd0b3ByaWdodCcsCiAgICAgICAgICAgICAgICAgY29sbGFwc2VkOiBmYWxzZSwKICAgICAgICAgICAgICAgICBhdXRvWkluZGV4OiB0cnVlCiAgICAgICAgICAgICAgICB9KS5hZGRUbyhtYXBfZWRhY2IxNzZmZTA3NDU0MGEwYjAyNDEyYTk0ZmFiNDIpOwogICAgICAgICAgICAKICAgICAgICAKPC9zY3JpcHQ+\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
      ],
      "text/plain": [
       "<folium.folium.Map at 0x947b128>"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Initialize map\n",
    "my_envelope_map = folium.Map(location=[49.5, 8.5], zoom_start=8)\n",
    "\n",
    "# Create an envelope polygon that contains some points\n",
    "list_of_points = randome_points(amount=10, LON_min=49.1, LON_max=50, LAT_min=8, LAT_max=9)\n",
    "\n",
    "create_envelope_polygon(my_envelope_map, list_of_points, layer_name='Example envelope',\n",
    "                        line_color='indianred', fill_color='red', weight=5, text='Example envelope')\n",
    "\n",
    "draw_points(my_envelope_map, list_of_points, layer_name='Example points for envelope',\n",
    "            line_color='darkred', fill_color='darkred', text='Example point for envelope')\n",
    "\n",
    "# Add layer control and show map\n",
    "folium.LayerControl(collapsed=False).add_to(my_envelope_map)\n",
    "my_envelope_map"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Concave hull (alpha shape)\n",
    "In some cases the convex hull does not yield good results - this is when the shape of the polygon should be concave instead of convex. The solution is a concave hull that is also called alpha shape. Yet, there is no ready to go, off the shelve solution for this but there are great resources (see: http://blog.thehumangeo.com/2014/05/12/drawing-boundaries-in-python/, accessed 04.01.2019 or https://towardsdatascience.com/the-concave-hull-c649795c0f0f, accessed 29.12.2018)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Main code\n",
    "Just putting it all together..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVM9ZmFsc2U7IExfTk9fVE9VQ0g9ZmFsc2U7IExfRElTQUJMRV8zRD1mYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4zLjQvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2FqYXguZ29vZ2xlYXBpcy5jb20vYWpheC9saWJzL2pxdWVyeS8xLjExLjEvanF1ZXJ5Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4zLjQvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdjZG4uZ2l0aGFjay5jb20vcHl0aG9uLXZpc3VhbGl6YXRpb24vZm9saXVtL21hc3Rlci9mb2xpdW0vdGVtcGxhdGVzL2xlYWZsZXQuYXdlc29tZS5yb3RhdGUuY3NzIi8+CiAgICA8c3R5bGU+aHRtbCwgYm9keSB7d2lkdGg6IDEwMCU7aGVpZ2h0OiAxMDAlO21hcmdpbjogMDtwYWRkaW5nOiAwO308L3N0eWxlPgogICAgPHN0eWxlPiNtYXAge3Bvc2l0aW9uOmFic29sdXRlO3RvcDowO2JvdHRvbTowO3JpZ2h0OjA7bGVmdDowO308L3N0eWxlPgogICAgCiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLAogICAgICAgIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEuMCwgdXNlci1zY2FsYWJsZT1ubyIgLz4KICAgIDxzdHlsZT4jbWFwXzBlZWE1NTkxZjYxYTRhOGJiMTAzMjEwMWMzNmIwMjllIHsKICAgICAgICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgICAgICAgd2lkdGg6IDEwMC4wJTsKICAgICAgICBoZWlnaHQ6IDEwMC4wJTsKICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgIHRvcDogMC4wJTsKICAgICAgICB9CiAgICA8L3N0eWxlPgo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgPGRpdiBjbGFzcz0iZm9saXVtLW1hcCIgaWQ9Im1hcF8wZWVhNTU5MWY2MWE0YThiYjEwMzIxMDFjMzZiMDI5ZSIgPjwvZGl2Pgo8L2JvZHk+CjxzY3JpcHQ+ICAgIAogICAgCiAgICAKICAgICAgICB2YXIgYm91bmRzID0gbnVsbDsKICAgIAoKICAgIHZhciBtYXBfMGVlYTU1OTFmNjFhNGE4YmIxMDMyMTAxYzM2YjAyOWUgPSBMLm1hcCgKICAgICAgICAnbWFwXzBlZWE1NTkxZjYxYTRhOGJiMTAzMjEwMWMzNmIwMjllJywgewogICAgICAgIGNlbnRlcjogWzQ4LjI0NjA2ODMsIDkuMjY3NjQxMjVdLAogICAgICAgIHpvb206IDcsCiAgICAgICAgbWF4Qm91bmRzOiBib3VuZHMsCiAgICAgICAgbGF5ZXJzOiBbXSwKICAgICAgICB3b3JsZENvcHlKdW1wOiBmYWxzZSwKICAgICAgICBjcnM6IEwuQ1JTLkVQU0czODU3LAogICAgICAgIHpvb21Db250cm9sOiB0cnVlLAogICAgICAgIH0pOwoKICAgIAogICAgCiAgICB2YXIgdGlsZV9sYXllcl8wN2RlN2JhMWY1ZTA0OWFjYjkxOGY4NTVkYzYxYmMxYyA9IEwudGlsZUxheWVyKAogICAgICAgICdodHRwczovL3tzfS50aWxlLm9wZW5zdHJlZXRtYXAub3JnL3t6fS97eH0ve3l9LnBuZycsCiAgICAgICAgewogICAgICAgICJhdHRyaWJ1dGlvbiI6IG51bGwsCiAgICAgICAgImRldGVjdFJldGluYSI6IGZhbHNlLAogICAgICAgICJtYXhOYXRpdmVab29tIjogMTgsCiAgICAgICAgIm1heFpvb20iOiAxOCwKICAgICAgICAibWluWm9vbSI6IDAsCiAgICAgICAgIm5vV3JhcCI6IGZhbHNlLAogICAgICAgICJvcGFjaXR5IjogMSwKICAgICAgICAic3ViZG9tYWlucyI6ICJhYmMiLAogICAgICAgICJ0bXMiOiBmYWxzZQp9KS5hZGRUbyhtYXBfMGVlYTU1OTFmNjFhNGE4YmIxMDMyMTAxYzM2YjAyOWUpOwogICAgCiAgICAgICAgICAgIHZhciBmZWF0dXJlX2dyb3VwXzk5MWE3M2I2YjdiZjQ0M2Y4Mjk0MDdiMDZkYzk1Y2NiID0gTC5mZWF0dXJlR3JvdXAoCiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8wZWVhNTU5MWY2MWE0YThiYjEwMzIxMDFjMzZiMDI5ZSk7CiAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBwb2x5Z29uXzdhOGVjMjRiZTc2YTRlYjk5OTcwMjA0YmM0ZjlmNTNhID0gTC5wb2x5Z29uKAogICAgICAgICAgICAgICAgW1s0OC45MTY3MzMxOTEyNDUzNywgOS4yNjk0MjQ3NjA5Mjc3MzJdLCBbNDguODc5MjMwMzI1MzYzOTIsIDkuOTIxMDczMTE1OTI2MjI4XSwgWzQ4LjIxOTkwMjQ3NzYyMDMxLCA5Ljc0MzgwOTQ0MzE1Nzk1N10sIFs0OC4xNjExNjcxMzEyNjI5NjQsIDkuMDY0NDc4ODI2ODcyMjI3XSwgWzQ4LjQyOTc4MTExMzQ5MjY2NiwgOS4wNDY0ODkwNzg4MjY0NF1dLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAibGlnaHRibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAibGlnaHRza3libHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjIsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJub0NsaXAiOiBmYWxzZSwKICAib3BhY2l0eSI6IDEuMCwKICAic21vb3RoRmFjdG9yIjogMS4wLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiA1Cn0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhmZWF0dXJlX2dyb3VwXzk5MWE3M2I2YjdiZjQ0M2Y4Mjk0MDdiMDZkYzk1Y2NiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2I4ZTlhODkzYjEzYjQ4NTA5YjkwMmQ2NDY5ZDgxZmZkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnCiAgICAgICAgICAgIAogICAgICAgICAgICB9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNWQzMjY5NmE4MmIxNDUxMmJhZmVkOGFiNmJiZDllMTMgPSAkKGA8ZGl2IGlkPSJodG1sXzVkMzI2OTZhODJiMTQ1MTJiYWZlZDhhYjZiYmQ5ZTEzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FeGFtcGxlIGNvbnZleCBodWxsPC9kaXY+YClbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iOGU5YTg5M2IxM2I0ODUwOWI5MDJkNjQ2OWQ4MWZmZC5zZXRDb250ZW50KGh0bWxfNWQzMjY5NmE4MmIxNDUxMmJhZmVkOGFiNmJiZDllMTMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIHBvbHlnb25fN2E4ZWMyNGJlNzZhNGViOTk5NzAyMDRiYzRmOWY1M2EuYmluZFBvcHVwKHBvcHVwX2I4ZTlhODkzYjEzYjQ4NTA5YjkwMmQ2NDY5ZDgxZmZkKQogICAgICAgICAgICA7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgZmVhdHVyZV9ncm91cF8wNzEzMDQxNjZjZjg0MjQxYmZlZDNiYTg1MDExNTJhOCA9IEwuZmVhdHVyZUdyb3VwKAogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMGVlYTU1OTFmNjFhNGE4YmIxMDMyMTAxYzM2YjAyOWUpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzZjOGZmZWY3NDc3NDRmMzQ5NzBhZmVkNWQ3YmJjMjU3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDguNTk0MDM4MTEwNTY1MDgsIDkuODE4NTQzOTY3NzA5ODVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAicm95YWxibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAicm95YWxibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjIsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhmZWF0dXJlX2dyb3VwXzA3MTMwNDE2NmNmODQyNDFiZmVkM2JhODUwMTE1MmE4KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzg5ZDFjYWI1OGM1MzQ5Njg5MDBlZDFhYmQ0YTUwYTBkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnCiAgICAgICAgICAgIAogICAgICAgICAgICB9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNWY0ODc4ZjdiMDYyNGY5Mjk0M2I2ZTYyNmIwOWIzYWMgPSAkKGA8ZGl2IGlkPSJodG1sXzVmNDg3OGY3YjA2MjRmOTI5NDNiNmU2MjZiMDliM2FjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FeGFtcGxlIHBvaW50IGZvciBjb252ZXggaHVsbDwvZGl2PmApWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfODlkMWNhYjU4YzUzNDk2ODkwMGVkMWFiZDRhNTBhMGQuc2V0Q29udGVudChodG1sXzVmNDg3OGY3YjA2MjRmOTI5NDNiNmU2MjZiMDliM2FjKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzZjOGZmZWY3NDc3NDRmMzQ5NzBhZmVkNWQ3YmJjMjU3LmJpbmRQb3B1cChwb3B1cF84OWQxY2FiNThjNTM0OTY4OTAwZWQxYWJkNGE1MGEwZCkKICAgICAgICAgICAgOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNjNmMmE3YmEzYTgxNDg4MzgzMWVhODIyMTUyMzUzNDUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OC4yMTk5MDI0Nzc2MjAzMSwgOS43NDM4MDk0NDMxNTc5NTddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAicm95YWxibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAicm95YWxibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjIsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhmZWF0dXJlX2dyb3VwXzA3MTMwNDE2NmNmODQyNDFiZmVkM2JhODUwMTE1MmE4KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2NjZjY1YTM0OTFmNzRiYTc5ZTFkMzVkM2EyNTMyNzBmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnCiAgICAgICAgICAgIAogICAgICAgICAgICB9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNTljMGJhY2MyYmI0NGRiYTlhYzM1N2VlZGJhYWM0YmIgPSAkKGA8ZGl2IGlkPSJodG1sXzU5YzBiYWNjMmJiNDRkYmE5YWMzNTdlZWRiYWFjNGJiIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FeGFtcGxlIHBvaW50IGZvciBjb252ZXggaHVsbDwvZGl2PmApWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfY2NmNjVhMzQ5MWY3NGJhNzllMWQzNWQzYTI1MzI3MGYuc2V0Q29udGVudChodG1sXzU5YzBiYWNjMmJiNDRkYmE5YWMzNTdlZWRiYWFjNGJiKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzYzZjJhN2JhM2E4MTQ4ODM4MzFlYTgyMjE1MjM1MzQ1LmJpbmRQb3B1cChwb3B1cF9jY2Y2NWEzNDkxZjc0YmE3OWUxZDM1ZDNhMjUzMjcwZikKICAgICAgICAgICAgOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNDZjZDM2YzYyZDlmNGY4NzliOTA4YjE0NWVlZDBlNWQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OC43NjA3MDc5NjEwNzI3NywgOS44NTk0MzI5MzY0NDMyMTVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAicm95YWxibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAicm95YWxibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjIsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhmZWF0dXJlX2dyb3VwXzA3MTMwNDE2NmNmODQyNDFiZmVkM2JhODUwMTE1MmE4KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzA0OTRhZTVhMzdhODRmNGFiYjM5MGVhODZjYjNjNTA4ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnCiAgICAgICAgICAgIAogICAgICAgICAgICB9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYjIwNmYwY2JiYTVlNDExNmJiNzA5MWUzMTIxMTNhMmYgPSAkKGA8ZGl2IGlkPSJodG1sX2IyMDZmMGNiYmE1ZTQxMTZiYjcwOTFlMzEyMTEzYTJmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FeGFtcGxlIHBvaW50IGZvciBjb252ZXggaHVsbDwvZGl2PmApWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMDQ5NGFlNWEzN2E4NGY0YWJiMzkwZWE4NmNiM2M1MDguc2V0Q29udGVudChodG1sX2IyMDZmMGNiYmE1ZTQxMTZiYjcwOTFlMzEyMTEzYTJmKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzQ2Y2QzNmM2MmQ5ZjRmODc5YjkwOGIxNDVlZWQwZTVkLmJpbmRQb3B1cChwb3B1cF8wNDk0YWU1YTM3YTg0ZjRhYmIzOTBlYTg2Y2IzYzUwOCkKICAgICAgICAgICAgOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMjkwZGU0ZDQ4MGU5NDQ5NGI4NmRkOTdiNmQ3M2QzYjQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OC4xNjExNjcxMzEyNjI5NjQsIDkuMDY0NDc4ODI2ODcyMjI3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogInJveWFsYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogInJveWFsYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC4yLAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8oZmVhdHVyZV9ncm91cF8wNzEzMDQxNjZjZjg0MjQxYmZlZDNiYTg1MDExNTJhOCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wNTAzMmMwN2U2Mjk0YzM1OTNiMTNkYTNmNzhiZTVhYyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJwogICAgICAgICAgICAKICAgICAgICAgICAgfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzAwNzY1NWIwMTE0YTQwZjFiYzFiNTE1MGY1ZjdjMjlhID0gJChgPGRpdiBpZD0iaHRtbF8wMDc2NTViMDExNGE0MGYxYmMxYjUxNTBmNWY3YzI5YSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RXhhbXBsZSBwb2ludCBmb3IgY29udmV4IGh1bGw8L2Rpdj5gKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzA1MDMyYzA3ZTYyOTRjMzU5M2IxM2RhM2Y3OGJlNWFjLnNldENvbnRlbnQoaHRtbF8wMDc2NTViMDExNGE0MGYxYmMxYjUxNTBmNWY3YzI5YSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yOTBkZTRkNDgwZTk0NDk0Yjg2ZGQ5N2I2ZDczZDNiNC5iaW5kUG9wdXAocG9wdXBfMDUwMzJjMDdlNjI5NGMzNTkzYjEzZGEzZjc4YmU1YWMpCiAgICAgICAgICAgIDsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzU4N2ZmMTY5ZTZmMTQ1ODk5ZDYzMTUyYTk4M2EzMjFiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDguOTE2NzMzMTkxMjQ1MzcsIDkuMjY5NDI0NzYwOTI3NzMyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogInJveWFsYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogInJveWFsYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC4yLAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8oZmVhdHVyZV9ncm91cF8wNzEzMDQxNjZjZjg0MjQxYmZlZDNiYTg1MDExNTJhOCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zNTllYmY1Y2M2Mjk0MzYxYmUwNGVjMzljNjFjNTJjZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJwogICAgICAgICAgICAKICAgICAgICAgICAgfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2ExNTI4ZGUyN2JlZTQ5NTI4ZjcwMDM0NGEyZWYzOGVlID0gJChgPGRpdiBpZD0iaHRtbF9hMTUyOGRlMjdiZWU0OTUyOGY3MDAzNDRhMmVmMzhlZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RXhhbXBsZSBwb2ludCBmb3IgY29udmV4IGh1bGw8L2Rpdj5gKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzM1OWViZjVjYzYyOTQzNjFiZTA0ZWMzOWM2MWM1MmNkLnNldENvbnRlbnQoaHRtbF9hMTUyOGRlMjdiZWU0OTUyOGY3MDAzNDRhMmVmMzhlZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl81ODdmZjE2OWU2ZjE0NTg5OWQ2MzE1MmE5ODNhMzIxYi5iaW5kUG9wdXAocG9wdXBfMzU5ZWJmNWNjNjI5NDM2MWJlMDRlYzM5YzYxYzUyY2QpCiAgICAgICAgICAgIDsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzY2ZDg3OWE3NDk4NjQxMzRhYzRjNjQ5M2UzNjA3M2E2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDguODc5MjMwMzI1MzYzOTIsIDkuOTIxMDczMTE1OTI2MjI4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogInJveWFsYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogInJveWFsYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC4yLAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8oZmVhdHVyZV9ncm91cF8wNzEzMDQxNjZjZjg0MjQxYmZlZDNiYTg1MDExNTJhOCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83MDcwMDJiNTM2Yjg0N2MxODZjNzdkYTQ4NmYwOGIyZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJwogICAgICAgICAgICAKICAgICAgICAgICAgfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzlkMmVkMjJmOWQyMTQzNWE5ZGY1ZmJhYWJmZmRmZDFkID0gJChgPGRpdiBpZD0iaHRtbF85ZDJlZDIyZjlkMjE0MzVhOWRmNWZiYWFiZmZkZmQxZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RXhhbXBsZSBwb2ludCBmb3IgY29udmV4IGh1bGw8L2Rpdj5gKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzcwNzAwMmI1MzZiODQ3YzE4NmM3N2RhNDg2ZjA4YjJmLnNldENvbnRlbnQoaHRtbF85ZDJlZDIyZjlkMjE0MzVhOWRmNWZiYWFiZmZkZmQxZCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82NmQ4NzlhNzQ5ODY0MTM0YWM0YzY0OTNlMzYwNzNhNi5iaW5kUG9wdXAocG9wdXBfNzA3MDAyYjUzNmI4NDdjMTg2Yzc3ZGE0ODZmMDhiMmYpCiAgICAgICAgICAgIDsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzNjYzkxZDY3ZDgwNTRjM2U4OGM5ZDEwNTk2MWRjOTNiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDguNDI5NzgxMTEzNDkyNjY2LCA5LjA0NjQ4OTA3ODgyNjQ0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogInJveWFsYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogInJveWFsYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC4yLAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8oZmVhdHVyZV9ncm91cF8wNzEzMDQxNjZjZjg0MjQxYmZlZDNiYTg1MDExNTJhOCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80OTFiYzk0YjEyNDI0YTdmODFhOTNhM2JlYmZkNWEwMiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJwogICAgICAgICAgICAKICAgICAgICAgICAgfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzZmMTNmNTNjZWJiNjQ5NWRhZjgyNzY4YzljMGYzYTY1ID0gJChgPGRpdiBpZD0iaHRtbF82ZjEzZjUzY2ViYjY0OTVkYWY4Mjc2OGM5YzBmM2E2NSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RXhhbXBsZSBwb2ludCBmb3IgY29udmV4IGh1bGw8L2Rpdj5gKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzQ5MWJjOTRiMTI0MjRhN2Y4MWE5M2EzYmViZmQ1YTAyLnNldENvbnRlbnQoaHRtbF82ZjEzZjUzY2ViYjY0OTVkYWY4Mjc2OGM5YzBmM2E2NSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8zY2M5MWQ2N2Q4MDU0YzNlODhjOWQxMDU5NjFkYzkzYi5iaW5kUG9wdXAocG9wdXBfNDkxYmM5NGIxMjQyNGE3ZjgxYTkzYTNiZWJmZDVhMDIpCiAgICAgICAgICAgIDsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2M5OTEwMjA4ODY3ZjRmOWRhYjM4M2Q3NmRjMzQ5ZDVmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDguNjM5MDY4MjUxNDUxNTUsIDkuMTk4Njg1NjQzNTI0NTE3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogInJveWFsYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogInJveWFsYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC4yLAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8oZmVhdHVyZV9ncm91cF8wNzEzMDQxNjZjZjg0MjQxYmZlZDNiYTg1MDExNTJhOCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mOGE2N2UzNjBhMTY0ZmI3YWE3YTlkNjQ4NjYxMmYzZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJwogICAgICAgICAgICAKICAgICAgICAgICAgfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2I4MWM3YTFkMjZmNDQ2ODJiYzU0ZWVmMDg1OGJjMzU1ID0gJChgPGRpdiBpZD0iaHRtbF9iODFjN2ExZDI2ZjQ0NjgyYmM1NGVlZjA4NThiYzM1NSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RXhhbXBsZSBwb2ludCBmb3IgY29udmV4IGh1bGw8L2Rpdj5gKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2Y4YTY3ZTM2MGExNjRmYjdhYTdhOWQ2NDg2NjEyZjNlLnNldENvbnRlbnQoaHRtbF9iODFjN2ExZDI2ZjQ0NjgyYmM1NGVlZjA4NThiYzM1NSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jOTkxMDIwODg2N2Y0ZjlkYWIzODNkNzZkYzM0OWQ1Zi5iaW5kUG9wdXAocG9wdXBfZjhhNjdlMzYwYTE2NGZiN2FhN2E5ZDY0ODY2MTJmM2UpCiAgICAgICAgICAgIDsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzQwOWY2MDJkM2RkNDQxMDU5MDBjOTdmNTQwZTRhMGI2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDguNTY3ODc5ODUyNzMzMSwgOS4zNDUzMjE4Mzg2NzMzMzVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAicm95YWxibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAicm95YWxibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjIsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhmZWF0dXJlX2dyb3VwXzA3MTMwNDE2NmNmODQyNDFiZmVkM2JhODUwMTE1MmE4KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2I2ZTcyNTBiYzMyMjQ5ZjdhNDY5YzAzMDA5OGNjY2JkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnCiAgICAgICAgICAgIAogICAgICAgICAgICB9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYmE0MjU3MDhjNTJiNDIwM2JlNjQzYWU3NzM0OTMyY2UgPSAkKGA8ZGl2IGlkPSJodG1sX2JhNDI1NzA4YzUyYjQyMDNiZTY0M2FlNzczNDkzMmNlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FeGFtcGxlIHBvaW50IGZvciBjb252ZXggaHVsbDwvZGl2PmApWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYjZlNzI1MGJjMzIyNDlmN2E0NjljMDMwMDk4Y2NjYmQuc2V0Q29udGVudChodG1sX2JhNDI1NzA4YzUyYjQyMDNiZTY0M2FlNzczNDkzMmNlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzQwOWY2MDJkM2RkNDQxMDU5MDBjOTdmNTQwZTRhMGI2LmJpbmRQb3B1cChwb3B1cF9iNmU3MjUwYmMzMjI0OWY3YTQ2OWMwMzAwOThjY2NiZCkKICAgICAgICAgICAgOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMjYxN2M4NGY1MDgxNGIzNjllMzIzNzIwMDY1NWExMDUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OC44NTQ1NTU0NTg4OTI1ODQsIDkuNTg1MDYwNjcxMTA0NjU3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogInJveWFsYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogInJveWFsYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC4yLAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8oZmVhdHVyZV9ncm91cF8wNzEzMDQxNjZjZjg0MjQxYmZlZDNiYTg1MDExNTJhOCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wYTllYzJhOTNiMDc0ZTY4ODJkNjNhMDliZGNmZWU5MyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJwogICAgICAgICAgICAKICAgICAgICAgICAgfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzA5Yzk1ZDQ3ZDZjZTQyYzI4ODg1MjMzNjFhNGNlZWI1ID0gJChgPGRpdiBpZD0iaHRtbF8wOWM5NWQ0N2Q2Y2U0MmMyODg4NTIzMzYxYTRjZWViNSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RXhhbXBsZSBwb2ludCBmb3IgY29udmV4IGh1bGw8L2Rpdj5gKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzBhOWVjMmE5M2IwNzRlNjg4MmQ2M2EwOWJkY2ZlZTkzLnNldENvbnRlbnQoaHRtbF8wOWM5NWQ0N2Q2Y2U0MmMyODg4NTIzMzYxYTRjZWViNSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yNjE3Yzg0ZjUwODE0YjM2OWUzMjM3MjAwNjU1YTEwNS5iaW5kUG9wdXAocG9wdXBfMGE5ZWMyYTkzYjA3NGU2ODgyZDYzYTA5YmRjZmVlOTMpCiAgICAgICAgICAgIDsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBmZWF0dXJlX2dyb3VwX2FhNWQ3ZDYzMGJlNzRhZTlhMTM0NGQ2MGVmNDUzOTBjID0gTC5mZWF0dXJlR3JvdXAoCiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8wZWVhNTU5MWY2MWE0YThiYjEwMzIxMDFjMzZiMDI5ZSk7CiAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBwb2x5Z29uXzcyOGUxYzg4NTMwZDQyNDhhYTQ4OTMxYzllYWJjYjg5ID0gTC5wb2x5Z29uKAogICAgICAgICAgICAgICAgW1s0OS4xODI4MTg4MTc0NTUxOSwgOC44ODkwNjk1MjU2MTM4ODhdLCBbNDkuOTIxMDY5MjM5MTI5MzksIDguODg5MDY5NTI1NjEzODg4XSwgWzQ5LjkyMTA2OTIzOTEyOTM5LCA4LjE1MTgzNzE3NDk3Nzc1XSwgWzQ5LjE4MjgxODgxNzQ1NTE5LCA4LjE1MTgzNzE3NDk3Nzc1XV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJpbmRpYW5yZWQiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJyZWQiLAogICJmaWxsT3BhY2l0eSI6IDAuMiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm5vQ2xpcCI6IGZhbHNlLAogICJvcGFjaXR5IjogMS4wLAogICJzbW9vdGhGYWN0b3IiOiAxLjAsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDUKfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKGZlYXR1cmVfZ3JvdXBfYWE1ZDdkNjMwYmU3NGFlOWExMzQ0ZDYwZWY0NTM5MGMpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMmY4NDZhZjllNmFiNGEyZmFhODY5YjljNTI4ZDczY2EgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCcKICAgICAgICAgICAgCiAgICAgICAgICAgIH0pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xZGQ3Njc2OThmZGI0ZGZlOWQ1MWEwMzkwMzYxYzAyYiA9ICQoYDxkaXYgaWQ9Imh0bWxfMWRkNzY3Njk4ZmRiNGRmZTlkNTFhMDM5MDM2MWMwMmIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkV4YW1wbGUgZW52ZWxvcGU8L2Rpdj5gKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzJmODQ2YWY5ZTZhYjRhMmZhYTg2OWI5YzUyOGQ3M2NhLnNldENvbnRlbnQoaHRtbF8xZGQ3Njc2OThmZGI0ZGZlOWQ1MWEwMzkwMzYxYzAyYik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgcG9seWdvbl83MjhlMWM4ODUzMGQ0MjQ4YWE0ODkzMWM5ZWFiY2I4OS5iaW5kUG9wdXAocG9wdXBfMmY4NDZhZjllNmFiNGEyZmFhODY5YjljNTI4ZDczY2EpCiAgICAgICAgICAgIDsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBmZWF0dXJlX2dyb3VwXzQ4NmJhYmMwYzE1NTRkZDc4MTg3YWRhZDhlYTQ1Y2YxID0gTC5mZWF0dXJlR3JvdXAoCiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8wZWVhNTU5MWY2MWE0YThiYjEwMzIxMDFjMzZiMDI5ZSk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMWE1ZDk5NWM0MmE1NDBiN2E1ZDc5ODkxMWU0NDNjMTggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OS4xODI4MTg4MTc0NTUxOSwgOC44ODkwNjk1MjU2MTM4ODhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiZGFya3JlZCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImRhcmtyZWQiLAogICJmaWxsT3BhY2l0eSI6IDAuMiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDEsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKGZlYXR1cmVfZ3JvdXBfNDg2YmFiYzBjMTU1NGRkNzgxODdhZGFkOGVhNDVjZjEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZjgyMmRmN2E5MzQ0NDg0M2E4YjU2ZTIwMzk4OTQxYmQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCcKICAgICAgICAgICAgCiAgICAgICAgICAgIH0pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9hOTY5ZDc4NTUzNWM0MzM3YmQ0OGExMDg5ZDE5MjhkMiA9ICQoYDxkaXYgaWQ9Imh0bWxfYTk2OWQ3ODU1MzVjNDMzN2JkNDhhMTA4OWQxOTI4ZDIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkV4YW1wbGUgcG9pbnQgZm9yIGVudmVsb3BlPC9kaXY+YClbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mODIyZGY3YTkzNDQ0ODQzYThiNTZlMjAzOTg5NDFiZC5zZXRDb250ZW50KGh0bWxfYTk2OWQ3ODU1MzVjNDMzN2JkNDhhMTA4OWQxOTI4ZDIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMWE1ZDk5NWM0MmE1NDBiN2E1ZDc5ODkxMWU0NDNjMTguYmluZFBvcHVwKHBvcHVwX2Y4MjJkZjdhOTM0NDQ4NDNhOGI1NmUyMDM5ODk0MWJkKQogICAgICAgICAgICA7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hMjIyYmYxMmEzOGE0YWQ1OTVhYWIzZTE5YTgzZjdkMSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ5LjUwOTk3NzYxNjI1ODQ0NiwgOC40ODkzMTA5MTAyOTIyMzhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiZGFya3JlZCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImRhcmtyZWQiLAogICJmaWxsT3BhY2l0eSI6IDAuMiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDEsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKGZlYXR1cmVfZ3JvdXBfNDg2YmFiYzBjMTU1NGRkNzgxODdhZGFkOGVhNDVjZjEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOGE5YTY3MDA2NDRjNGE1NTljM2I5OWNkMzg1ZWEzZjMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCcKICAgICAgICAgICAgCiAgICAgICAgICAgIH0pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jZWE1N2YwYWUzMjI0NTAyOGQ2NDZjMzFmMjM2ZGE5NCA9ICQoYDxkaXYgaWQ9Imh0bWxfY2VhNTdmMGFlMzIyNDUwMjhkNjQ2YzMxZjIzNmRhOTQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkV4YW1wbGUgcG9pbnQgZm9yIGVudmVsb3BlPC9kaXY+YClbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84YTlhNjcwMDY0NGM0YTU1OWMzYjk5Y2QzODVlYTNmMy5zZXRDb250ZW50KGh0bWxfY2VhNTdmMGFlMzIyNDUwMjhkNjQ2YzMxZjIzNmRhOTQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYTIyMmJmMTJhMzhhNGFkNTk1YWFiM2UxOWE4M2Y3ZDEuYmluZFBvcHVwKHBvcHVwXzhhOWE2NzAwNjQ0YzRhNTU5YzNiOTljZDM4NWVhM2YzKQogICAgICAgICAgICA7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl82Zjc2Y2U0YWUxZDU0MWMwYTIzYTI4MTBiMGQxOWFmNyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ5LjI2ODc2ODkzNjg1NjAwNiwgOC41NzY1ODE3NDk2NDkyNzddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiZGFya3JlZCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImRhcmtyZWQiLAogICJmaWxsT3BhY2l0eSI6IDAuMiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDEsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKGZlYXR1cmVfZ3JvdXBfNDg2YmFiYzBjMTU1NGRkNzgxODdhZGFkOGVhNDVjZjEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMWYxYzhiN2M5YzBkNDI5ZDlkZjRhOTAxNDEzMzVkNjUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCcKICAgICAgICAgICAgCiAgICAgICAgICAgIH0pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83NmU1MzcwMzZjN2U0NTQ0YTIxOGUzOWM2NTQxYzgyNSA9ICQoYDxkaXYgaWQ9Imh0bWxfNzZlNTM3MDM2YzdlNDU0NGEyMThlMzljNjU0MWM4MjUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkV4YW1wbGUgcG9pbnQgZm9yIGVudmVsb3BlPC9kaXY+YClbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8xZjFjOGI3YzljMGQ0MjlkOWRmNGE5MDE0MTMzNWQ2NS5zZXRDb250ZW50KGh0bWxfNzZlNTM3MDM2YzdlNDU0NGEyMThlMzljNjU0MWM4MjUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNmY3NmNlNGFlMWQ1NDFjMGEyM2EyODEwYjBkMTlhZjcuYmluZFBvcHVwKHBvcHVwXzFmMWM4YjdjOWMwZDQyOWQ5ZGY0YTkwMTQxMzM1ZDY1KQogICAgICAgICAgICA7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80NmRhMTk0YTlhOTE0ZTFmYWJlYzdjMWMxZmUwYjBkNSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ5Ljg2MzkxMjY3NDU5MjUxLCA4LjQxMjA2OTkzMDYwMjI4Nl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJkYXJrcmVkIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiZGFya3JlZCIsCiAgImZpbGxPcGFjaXR5IjogMC4yLAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8oZmVhdHVyZV9ncm91cF80ODZiYWJjMGMxNTU0ZGQ3ODE4N2FkYWQ4ZWE0NWNmMSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83MTEyMDI4ZjkxYzc0YmU0YTIwMDNmMGQzZDFjMWUzMCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJwogICAgICAgICAgICAKICAgICAgICAgICAgfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzllYWIyNGJmOGI4MDRmMDA5YzBjZDZjZTA2ZWRlYmE5ID0gJChgPGRpdiBpZD0iaHRtbF85ZWFiMjRiZjhiODA0ZjAwOWMwY2Q2Y2UwNmVkZWJhOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RXhhbXBsZSBwb2ludCBmb3IgZW52ZWxvcGU8L2Rpdj5gKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzcxMTIwMjhmOTFjNzRiZTRhMjAwM2YwZDNkMWMxZTMwLnNldENvbnRlbnQoaHRtbF85ZWFiMjRiZjhiODA0ZjAwOWMwY2Q2Y2UwNmVkZWJhOSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl80NmRhMTk0YTlhOTE0ZTFmYWJlYzdjMWMxZmUwYjBkNS5iaW5kUG9wdXAocG9wdXBfNzExMjAyOGY5MWM3NGJlNGEyMDAzZjBkM2QxYzFlMzApCiAgICAgICAgICAgIDsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzE1OGU2NDNiZTk0YzRlMTBiODk3NTFiZjg5OTMxYmU2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDkuMjAwMTI4NjAyOTIxNTI0LCA4LjM0NDE3MzU5NzI3NTEyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImRhcmtyZWQiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJkYXJrcmVkIiwKICAiZmlsbE9wYWNpdHkiOiAwLjIsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhmZWF0dXJlX2dyb3VwXzQ4NmJhYmMwYzE1NTRkZDc4MTg3YWRhZDhlYTQ1Y2YxKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzFiMzEwOTI0MWIxYjRjOTA5OWQxYmVlNzFkNzQ0MDhlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnCiAgICAgICAgICAgIAogICAgICAgICAgICB9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMjhkYmM4Y2YwYzMwNDJkMDgyNDk2NDJkZDkyOTkwZTggPSAkKGA8ZGl2IGlkPSJodG1sXzI4ZGJjOGNmMGMzMDQyZDA4MjQ5NjQyZGQ5Mjk5MGU4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FeGFtcGxlIHBvaW50IGZvciBlbnZlbG9wZTwvZGl2PmApWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMWIzMTA5MjQxYjFiNGM5MDk5ZDFiZWU3MWQ3NDQwOGUuc2V0Q29udGVudChodG1sXzI4ZGJjOGNmMGMzMDQyZDA4MjQ5NjQyZGQ5Mjk5MGU4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzE1OGU2NDNiZTk0YzRlMTBiODk3NTFiZjg5OTMxYmU2LmJpbmRQb3B1cChwb3B1cF8xYjMxMDkyNDFiMWI0YzkwOTlkMWJlZTcxZDc0NDA4ZSkKICAgICAgICAgICAgOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZGIzMzFmY2U0NThkNDIwMWJhMDYzMGVhNzlmZWUwOWMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OS45MTYyMDExOTEwNTYwNywgOC4yODQ4OTg5Mjg2ODA0MDRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiZGFya3JlZCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImRhcmtyZWQiLAogICJmaWxsT3BhY2l0eSI6IDAuMiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDEsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKGZlYXR1cmVfZ3JvdXBfNDg2YmFiYzBjMTU1NGRkNzgxODdhZGFkOGVhNDVjZjEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNzc0NjNjYjQzMzE1NGM0MDlkODhmM2NhMTg1MmQ1NGQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCcKICAgICAgICAgICAgCiAgICAgICAgICAgIH0pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF85NTdjZDNiNTM1YWM0MTQzYmFhMDFlODcwOGEzZjhmZSA9ICQoYDxkaXYgaWQ9Imh0bWxfOTU3Y2QzYjUzNWFjNDE0M2JhYTAxZTg3MDhhM2Y4ZmUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkV4YW1wbGUgcG9pbnQgZm9yIGVudmVsb3BlPC9kaXY+YClbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83NzQ2M2NiNDMzMTU0YzQwOWQ4OGYzY2ExODUyZDU0ZC5zZXRDb250ZW50KGh0bWxfOTU3Y2QzYjUzNWFjNDE0M2JhYTAxZTg3MDhhM2Y4ZmUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZGIzMzFmY2U0NThkNDIwMWJhMDYzMGVhNzlmZWUwOWMuYmluZFBvcHVwKHBvcHVwXzc3NDYzY2I0MzMxNTRjNDA5ZDg4ZjNjYTE4NTJkNTRkKQogICAgICAgICAgICA7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xMzUwMGM2NTFiYzM0Nzg2YWZiYWNmYzA5YTY2NjVhYyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ5LjU3MDgwNzE1NjUyNjI0LCA4Ljc0NTI1NTc4NDcwODgxOV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJkYXJrcmVkIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiZGFya3JlZCIsCiAgImZpbGxPcGFjaXR5IjogMC4yLAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8oZmVhdHVyZV9ncm91cF80ODZiYWJjMGMxNTU0ZGQ3ODE4N2FkYWQ4ZWE0NWNmMSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9lNjAzNzNmZmRmM2M0OWMxYWU1ZjY0ZmUwYzYzMGZmNiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJwogICAgICAgICAgICAKICAgICAgICAgICAgfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2ZjYjRjZDI1MDY3MDQwYjA4NWUxOTI0ZDY3MmUzZWNhID0gJChgPGRpdiBpZD0iaHRtbF9mY2I0Y2QyNTA2NzA0MGIwODVlMTkyNGQ2NzJlM2VjYSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RXhhbXBsZSBwb2ludCBmb3IgZW52ZWxvcGU8L2Rpdj5gKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2U2MDM3M2ZmZGYzYzQ5YzFhZTVmNjRmZTBjNjMwZmY2LnNldENvbnRlbnQoaHRtbF9mY2I0Y2QyNTA2NzA0MGIwODVlMTkyNGQ2NzJlM2VjYSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8xMzUwMGM2NTFiYzM0Nzg2YWZiYWNmYzA5YTY2NjVhYy5iaW5kUG9wdXAocG9wdXBfZTYwMzczZmZkZjNjNDljMWFlNWY2NGZlMGM2MzBmZjYpCiAgICAgICAgICAgIDsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2QyYzg5ZDI3OTAxMzQyMTE4ODY5YzAzOTNlODNmZmI4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDkuMzQ1Mjc2NjU0NjEwMzksIDguNzEzNzgyNjMzOTQxOTczXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImRhcmtyZWQiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJkYXJrcmVkIiwKICAiZmlsbE9wYWNpdHkiOiAwLjIsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhmZWF0dXJlX2dyb3VwXzQ4NmJhYmMwYzE1NTRkZDc4MTg3YWRhZDhlYTQ1Y2YxKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2I5NjM5ZGI1NDY5NDRlYzRiZTMyYzA2MWQ2ZDJhOTFkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnCiAgICAgICAgICAgIAogICAgICAgICAgICB9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZTQzMzIwMWFmYWYxNGQ2YmJjMGYwMTUwYjMwNDdmM2QgPSAkKGA8ZGl2IGlkPSJodG1sX2U0MzMyMDFhZmFmMTRkNmJiYzBmMDE1MGIzMDQ3ZjNkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FeGFtcGxlIHBvaW50IGZvciBlbnZlbG9wZTwvZGl2PmApWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYjk2MzlkYjU0Njk0NGVjNGJlMzJjMDYxZDZkMmE5MWQuc2V0Q29udGVudChodG1sX2U0MzMyMDFhZmFmMTRkNmJiYzBmMDE1MGIzMDQ3ZjNkKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2QyYzg5ZDI3OTAxMzQyMTE4ODY5YzAzOTNlODNmZmI4LmJpbmRQb3B1cChwb3B1cF9iOTYzOWRiNTQ2OTQ0ZWM0YmUzMmMwNjFkNmQyYTkxZCkKICAgICAgICAgICAgOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOWIwOTM2ZGFlMWI4NDVhMDk4NDg4NTIwMzJkZTJhYzggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OS43OTc5ODMzNjg5MzM1NDQsIDguNjY4MzExNzc4MjkxMjc0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImRhcmtyZWQiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJkYXJrcmVkIiwKICAiZmlsbE9wYWNpdHkiOiAwLjIsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhmZWF0dXJlX2dyb3VwXzQ4NmJhYmMwYzE1NTRkZDc4MTg3YWRhZDhlYTQ1Y2YxKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2MxYjU5NDZjYWYzMjQxMDA4MDYwYWI5ZTE3NWZlNTc1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnCiAgICAgICAgICAgIAogICAgICAgICAgICB9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNjRmNmJmN2M1MzZmNDRhNGIwY2YyYWQxNjFmODMyNDYgPSAkKGA8ZGl2IGlkPSJodG1sXzY0ZjZiZjdjNTM2ZjQ0YTRiMGNmMmFkMTYxZjgzMjQ2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FeGFtcGxlIHBvaW50IGZvciBlbnZlbG9wZTwvZGl2PmApWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYzFiNTk0NmNhZjMyNDEwMDgwNjBhYjllMTc1ZmU1NzUuc2V0Q29udGVudChodG1sXzY0ZjZiZjdjNTM2ZjQ0YTRiMGNmMmFkMTYxZjgzMjQ2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzliMDkzNmRhZTFiODQ1YTA5ODQ4ODUyMDMyZGUyYWM4LmJpbmRQb3B1cChwb3B1cF9jMWI1OTQ2Y2FmMzI0MTAwODA2MGFiOWUxNzVmZTU3NSkKICAgICAgICAgICAgOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZmRhMDYwYTI4YWQyNGE3OGI3MTMyNWEwMGJmODY5ZjMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OS45MjEwNjkyMzkxMjkzOSwgOC4xNTE4MzcxNzQ5Nzc3NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJkYXJrcmVkIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiZGFya3JlZCIsCiAgImZpbGxPcGFjaXR5IjogMC4yLAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8oZmVhdHVyZV9ncm91cF80ODZiYWJjMGMxNTU0ZGQ3ODE4N2FkYWQ4ZWE0NWNmMSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iNzNjMDhjNTM4ZDA0Mjc0YmY4NTNlYTMxNGFkNWMyYiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJwogICAgICAgICAgICAKICAgICAgICAgICAgfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2MwNWVjZmY0OWMwMTQxN2RhNzdkZWJhMWRmMjVmNWFiID0gJChgPGRpdiBpZD0iaHRtbF9jMDVlY2ZmNDljMDE0MTdkYTc3ZGViYTFkZjI1ZjVhYiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RXhhbXBsZSBwb2ludCBmb3IgZW52ZWxvcGU8L2Rpdj5gKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2I3M2MwOGM1MzhkMDQyNzRiZjg1M2VhMzE0YWQ1YzJiLnNldENvbnRlbnQoaHRtbF9jMDVlY2ZmNDljMDE0MTdkYTc3ZGViYTFkZjI1ZjVhYik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mZGEwNjBhMjhhZDI0YTc4YjcxMzI1YTAwYmY4NjlmMy5iaW5kUG9wdXAocG9wdXBfYjczYzA4YzUzOGQwNDI3NGJmODUzZWEzMTRhZDVjMmIpCiAgICAgICAgICAgIDsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBsYXllcl9jb250cm9sX2FhZDM1Zjg1ZTg1ODRjOWI5YjAzMWQ4YzFjMzUwZTlmID0gewogICAgICAgICAgICAgICAgYmFzZV9sYXllcnMgOiB7ICJvcGVuc3RyZWV0bWFwIiA6IHRpbGVfbGF5ZXJfMDdkZTdiYTFmNWUwNDlhY2I5MThmODU1ZGM2MWJjMWMsIH0sCiAgICAgICAgICAgICAgICBvdmVybGF5cyA6IHsgIkV4YW1wbGUgY29udmV4IGh1bGwiIDogZmVhdHVyZV9ncm91cF85OTFhNzNiNmI3YmY0NDNmODI5NDA3YjA2ZGM5NWNjYiwiRXhhbXBsZSBwb2ludHMgZm9yIGNvbnZleCBodWxsIiA6IGZlYXR1cmVfZ3JvdXBfMDcxMzA0MTY2Y2Y4NDI0MWJmZWQzYmE4NTAxMTUyYTgsIkV4YW1wbGUgZW52ZWxvcGUiIDogZmVhdHVyZV9ncm91cF9hYTVkN2Q2MzBiZTc0YWU5YTEzNDRkNjBlZjQ1MzkwYywiRXhhbXBsZSBwb2ludHMgZm9yIGVudmVsb3BlIiA6IGZlYXR1cmVfZ3JvdXBfNDg2YmFiYzBjMTU1NGRkNzgxODdhZGFkOGVhNDVjZjEsIH0KICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgIEwuY29udHJvbC5sYXllcnMoCiAgICAgICAgICAgICAgICBsYXllcl9jb250cm9sX2FhZDM1Zjg1ZTg1ODRjOWI5YjAzMWQ4YzFjMzUwZTlmLmJhc2VfbGF5ZXJzLAogICAgICAgICAgICAgICAgbGF5ZXJfY29udHJvbF9hYWQzNWY4NWU4NTg0YzliOWIwMzFkOGMxYzM1MGU5Zi5vdmVybGF5cywKICAgICAgICAgICAgICAgIHtwb3NpdGlvbjogJ3RvcHJpZ2h0JywKICAgICAgICAgICAgICAgICBjb2xsYXBzZWQ6IGZhbHNlLAogICAgICAgICAgICAgICAgIGF1dG9aSW5kZXg6IHRydWUKICAgICAgICAgICAgICAgIH0pLmFkZFRvKG1hcF8wZWVhNTU5MWY2MWE0YThiYjEwMzIxMDFjMzZiMDI5ZSk7CiAgICAgICAgICAgIAogICAgICAgIAo8L3NjcmlwdD4=\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
      ],
      "text/plain": [
       "<folium.folium.Map at 0x94ac390>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Initialize map\n",
    "my_map_global = folium.Map(location=[48.2460683, 9.26764125], zoom_start=7)\n",
    "\n",
    "# Create a convex hull polygon that contains some points\n",
    "list_of_points = randome_points(amount=10, LON_min=48, LON_max=49, LAT_min=9, LAT_max=10)\n",
    "\n",
    "create_convexhull_polygon(my_map_global, list_of_points, layer_name='Example convex hull',\n",
    "                        line_color='lightblue', fill_color='lightskyblue', weight=5, text='Example convex hull') \n",
    "\n",
    "draw_points(my_map_global, list_of_points, layer_name='Example points for convex hull',\n",
    "           line_color='royalblue', fill_color='royalblue', text='Example point for convex hull')\n",
    "\n",
    "# Create an envelope polygon that contains some points\n",
    "list_of_points = randome_points(amount=10, LON_min=49.1, LON_max=50, LAT_min=8, LAT_max=9)\n",
    "\n",
    "create_envelope_polygon(my_map_global, list_of_points, layer_name='Example envelope',\n",
    "                      line_color='indianred', fill_color='red', weight=5, text='Example envelope')\n",
    "\n",
    "draw_points(my_map_global, list_of_points, layer_name='Example points for envelope',\n",
    "            line_color='darkred', fill_color='darkred', text='Example point for envelope')\n",
    "\n",
    "# Add layer control and show map\n",
    "folium.LayerControl(collapsed=False).add_to(my_map_global)\n",
    "my_map_global"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Sources:\n",
    "\n",
    "* http://blog.yhat.com/posts/interactive-geospatial-analysis.html, accessed 28.12.2018\n",
    "\n",
    "* https://docs.scipy.org/doc/scipy-0.19.0/reference/generated/scipy.spatial.ConvexHull.html, accessed 29.12.2018\n",
    "\n",
    "* https://www.oreilly.com/ideas/an-elegant-solution-to-the-convex-hull-problem, accessed 29.12.2018\n",
    "\n",
    "* https://medium.com/@vworri/simple-geospacial-mapping-with-geopandas-and-the-usual-suspects-77f46d40e807, accessed 29.12.2018\n",
    "\n",
    "* https://towardsdatascience.com/the-concave-hull-c649795c0f0f, accessed 29.12.2018\n",
    "\n",
    "* http://blog.thehumangeo.com/2014/05/12/drawing-boundaries-in-python/, accessed 04.01.2019\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
